Generic For Loops
This commit is contained in:
parent
2db4d0607e
commit
638394d25b
|
@ -1,8 +0,0 @@
|
||||||
namespace Upsilon.BaseTypes.LuaTypeInterfaces
|
|
||||||
{
|
|
||||||
public interface IIterable
|
|
||||||
{
|
|
||||||
bool Next(out LuaType key, out LuaType next);
|
|
||||||
void Reset();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,12 +2,12 @@ using System.Globalization;
|
||||||
|
|
||||||
namespace Upsilon.BaseTypes.Number
|
namespace Upsilon.BaseTypes.Number
|
||||||
{
|
{
|
||||||
internal class NumberDouble : Number
|
internal class ScriptNumberDouble : ScriptNumber
|
||||||
{
|
{
|
||||||
public double Value { get; }
|
public double Value { get; }
|
||||||
protected override bool IsFloat { get; } = true;
|
protected override bool IsFloat { get; } = true;
|
||||||
|
|
||||||
public NumberDouble(double value)
|
public ScriptNumberDouble(double value)
|
||||||
{
|
{
|
||||||
Value = value;
|
Value = value;
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ namespace Upsilon.BaseTypes.Number
|
||||||
return Value.ToString(CultureInfo.InvariantCulture);
|
return Value.ToString(CultureInfo.InvariantCulture);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static implicit operator double(NumberDouble n)
|
public static implicit operator double(ScriptNumberDouble n)
|
||||||
{
|
{
|
||||||
return n.Value;
|
return n.Value;
|
||||||
}
|
}
|
|
@ -3,12 +3,12 @@ using System.Globalization;
|
||||||
|
|
||||||
namespace Upsilon.BaseTypes.Number
|
namespace Upsilon.BaseTypes.Number
|
||||||
{
|
{
|
||||||
internal class NumberLong : Number
|
internal class ScriptNumberLong : ScriptNumber
|
||||||
{
|
{
|
||||||
public long Value { get; set; }
|
public long Value { get; set; }
|
||||||
protected override bool IsFloat { get; } = false;
|
protected override bool IsFloat { get; } = false;
|
||||||
|
|
||||||
public NumberLong(long val)
|
public ScriptNumberLong(long val)
|
||||||
{
|
{
|
||||||
Value = val;
|
Value = val;
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ namespace Upsilon.BaseTypes.Number
|
||||||
return Value.ToString(CultureInfo.InvariantCulture);
|
return Value.ToString(CultureInfo.InvariantCulture);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static implicit operator long(NumberLong n)
|
public static implicit operator long(ScriptNumberLong n)
|
||||||
{
|
{
|
||||||
if (n == null)
|
if (n == null)
|
||||||
return 0;
|
return 0;
|
|
@ -1,8 +1,8 @@
|
||||||
namespace Upsilon.BaseTypes
|
namespace Upsilon.BaseTypes
|
||||||
{
|
{
|
||||||
internal class LuaBoolean : LuaType
|
internal class ScriptBoolean : ScriptType
|
||||||
{
|
{
|
||||||
public LuaBoolean(bool value)
|
public ScriptBoolean(bool value)
|
||||||
{
|
{
|
||||||
Value = value;
|
Value = value;
|
||||||
}
|
}
|
||||||
|
@ -20,19 +20,19 @@ namespace Upsilon.BaseTypes
|
||||||
|
|
||||||
public bool Value { get; }
|
public bool Value { get; }
|
||||||
|
|
||||||
public static implicit operator bool(LuaBoolean b)
|
public static implicit operator bool(ScriptBoolean b)
|
||||||
{
|
{
|
||||||
return b.Value;
|
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()
|
public override string ToString()
|
|
@ -1,14 +1,14 @@
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Upsilon.BaseTypes.LuaTypeInterfaces;
|
using Upsilon.BaseTypes.ScriptTypeInterfaces;
|
||||||
using Upsilon.BaseTypes.UserData;
|
using Upsilon.BaseTypes.UserData;
|
||||||
using Upsilon.Binder;
|
using Upsilon.Binder;
|
||||||
using Upsilon.Evaluator;
|
using Upsilon.Evaluator;
|
||||||
|
|
||||||
namespace Upsilon.BaseTypes
|
namespace Upsilon.BaseTypes
|
||||||
{
|
{
|
||||||
internal abstract class LuaFunction : LuaType
|
internal abstract class ScriptFunction : ScriptType
|
||||||
{
|
{
|
||||||
public override Type Type => Type.Function;
|
public override Type Type => Type.Function;
|
||||||
public override object ToCSharpObject()
|
public override object ToCSharpObject()
|
||||||
|
@ -21,16 +21,16 @@ namespace Upsilon.BaseTypes
|
||||||
return null;
|
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 BoundBlockStatement Block { get; }
|
||||||
public ImmutableArray<VariableSymbol> Parameters { get; }
|
public ImmutableArray<VariableSymbol> Parameters { get; }
|
||||||
public EvaluationScope EvaluationScope { get; }
|
public EvaluationScope EvaluationScope { get; }
|
||||||
|
|
||||||
public LuaInternalFunction(ImmutableArray<VariableSymbol> parameters, BoundBlockStatement block,
|
public ScriptInternalFunction(ImmutableArray<VariableSymbol> parameters, BoundBlockStatement block,
|
||||||
EvaluationScope evaluationScope)
|
EvaluationScope evaluationScope)
|
||||||
{
|
{
|
||||||
Parameters = parameters;
|
Parameters = parameters;
|
||||||
|
@ -38,22 +38,22 @@ namespace Upsilon.BaseTypes
|
||||||
EvaluationScope = evaluationScope;
|
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);
|
var innerEvaluator = new Evaluator.Evaluator(diagnostics, EvaluationScope);
|
||||||
for (var i = 0; i < Parameters.Length; i++)
|
for (var i = 0; i < Parameters.Length; i++)
|
||||||
{
|
{
|
||||||
var parameterVariable = Parameters[i];
|
var parameterVariable = Parameters[i];
|
||||||
var parameterValue = variables[i];
|
var parameterValue = variables[i];
|
||||||
innerEvaluator.Scope.Set(parameterVariable, parameterValue);
|
innerEvaluator.Scope.Set(parameterVariable, parameterValue, true);
|
||||||
}
|
}
|
||||||
return innerEvaluator.EvaluateNode(Block);
|
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;
|
_method = method;
|
||||||
_object = o;
|
_object = o;
|
||||||
|
@ -62,7 +62,7 @@ namespace Upsilon.BaseTypes
|
||||||
private readonly UserDataMethod _method;
|
private readonly UserDataMethod _method;
|
||||||
private readonly object _object;
|
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 types = variables.Select(x => x.GetCSharpType());
|
||||||
var method = _method.GetMethod(types.ToArray());
|
var method = _method.GetMethod(types.ToArray());
|
|
@ -1,6 +1,6 @@
|
||||||
namespace Upsilon.BaseTypes
|
namespace Upsilon.BaseTypes
|
||||||
{
|
{
|
||||||
internal class LuaNull : LuaType
|
internal class ScriptNull : ScriptType
|
||||||
{
|
{
|
||||||
public override Type Type => Type.Nil;
|
public override Type Type => Type.Nil;
|
||||||
public override object ToCSharpObject()
|
public override object ToCSharpObject()
|
|
@ -1,13 +1,14 @@
|
||||||
using System;
|
using System;
|
||||||
using Upsilon.BaseTypes.Number;
|
using Upsilon.BaseTypes.Number;
|
||||||
|
using Upsilon.BaseTypes.ScriptTypeInterfaces;
|
||||||
using Upsilon.Evaluator;
|
using Upsilon.Evaluator;
|
||||||
using Upsilon.Text;
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.BaseTypes
|
namespace Upsilon.BaseTypes
|
||||||
{
|
{
|
||||||
internal class LuaString : LuaType, IIndexable
|
internal class ScriptString : ScriptType, IIndexable
|
||||||
{
|
{
|
||||||
public LuaString(string value)
|
public ScriptString(string value)
|
||||||
{
|
{
|
||||||
Value = value;
|
Value = value;
|
||||||
}
|
}
|
||||||
|
@ -28,7 +29,7 @@ namespace Upsilon.BaseTypes
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
return false;
|
return false;
|
||||||
if (!(obj is LuaString s))
|
if (!(obj is ScriptString s))
|
||||||
return false;
|
return false;
|
||||||
return Equals(s);
|
return Equals(s);
|
||||||
}
|
}
|
||||||
|
@ -38,45 +39,45 @@ namespace Upsilon.BaseTypes
|
||||||
return (Value != null ? Value.GetHashCode() : 0);
|
return (Value != null ? Value.GetHashCode() : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool Equals(LuaString s)
|
private bool Equals(ScriptString s)
|
||||||
{
|
{
|
||||||
return s != null && string.Equals(s.Value, Value);
|
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)
|
switch (b)
|
||||||
{
|
{
|
||||||
case LuaString s:
|
case ScriptString s:
|
||||||
return a + s;
|
return a + s;
|
||||||
case LuaBoolean bl:
|
case ScriptBoolean bl:
|
||||||
return a + bl;
|
return a + bl;
|
||||||
case NumberLong l:
|
case ScriptNumberLong l:
|
||||||
return a + l;
|
return a + l;
|
||||||
case NumberDouble d:
|
case ScriptNumberDouble d:
|
||||||
return a + d;
|
return a + d;
|
||||||
}
|
}
|
||||||
throw new ArgumentException($"Adding Type '{b.Type}' to a LuaString is not supported.");
|
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()
|
public override string ToString()
|
||||||
|
@ -84,27 +85,27 @@ namespace Upsilon.BaseTypes
|
||||||
return Value;
|
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;
|
int i;
|
||||||
if (index.Type == Type.String)
|
if (index.Type == Type.String)
|
||||||
{
|
{
|
||||||
var str = (LuaString)index;
|
var str = (ScriptString)index;
|
||||||
i = int.Parse(str.Value);
|
i = int.Parse(str.Value);
|
||||||
}
|
}
|
||||||
else if (index.Type == Type.Number)
|
else if (index.Type == Type.Number)
|
||||||
{
|
{
|
||||||
var ind = (Number.NumberLong) index;
|
var ind = (Number.ScriptNumberLong) index;
|
||||||
i = (int) ind.Value;
|
i = (int) ind.Value;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return null;
|
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();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
|
@ -1,17 +1,17 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Upsilon.BaseTypes.LuaTypeInterfaces;
|
using Upsilon.BaseTypes.ScriptTypeInterfaces;
|
||||||
using Upsilon.Binder;
|
using Upsilon.Binder;
|
||||||
using Upsilon.Evaluator;
|
using Upsilon.Evaluator;
|
||||||
using Upsilon.Text;
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.BaseTypes
|
namespace Upsilon.BaseTypes
|
||||||
{
|
{
|
||||||
internal class LuaTable : LuaType, IIndexable, IScopeOwner, IIterable
|
internal class ScriptTable : ScriptType, IIndexable, IScopeOwner, IIterable
|
||||||
{
|
{
|
||||||
public EvaluationScope EvaluationScope { get; }
|
public EvaluationScope EvaluationScope { get; }
|
||||||
|
|
||||||
public LuaTable(EvaluationScope scope)
|
public ScriptTable(EvaluationScope scope)
|
||||||
{
|
{
|
||||||
EvaluationScope = scope;
|
EvaluationScope = scope;
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ namespace Upsilon.BaseTypes
|
||||||
return typeof(Dictionary<string, object>);
|
return typeof(Dictionary<string, object>);
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
var s = index.ToString();
|
||||||
if (EvaluationScope.TryGet(s, out var o))
|
if (EvaluationScope.TryGet(s, out var o))
|
||||||
|
@ -35,36 +35,26 @@ namespace Upsilon.BaseTypes
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
diagnostics.LogError("Cannot find member 's' on Table", span);
|
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();
|
var s = index.ToString();
|
||||||
EvaluationScope.Set(new VariableSymbol(s, value.Type, false), value);
|
EvaluationScope.Set(new VariableSymbol(s, value.Type, false), value, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerator<(string Key, ScriptType value)> GetEnumerator()
|
||||||
private IEnumerator<KeyValuePair<string, LuaType>> _enumerator;
|
|
||||||
|
|
||||||
public bool Next(out LuaType key, out LuaType next)
|
|
||||||
{
|
{
|
||||||
if (_enumerator == null) _enumerator = EvaluationScope.Variables.GetEnumerator();
|
return Enumerator();
|
||||||
if (_enumerator.MoveNext())
|
}
|
||||||
|
|
||||||
|
private IEnumerator<(string Key, ScriptType value)> Enumerator()
|
||||||
|
{
|
||||||
|
foreach (var variable in EvaluationScope.Variables)
|
||||||
{
|
{
|
||||||
key = _enumerator.Current.Key.ToLuaType();
|
yield return (variable.Key, variable.Value);
|
||||||
next = _enumerator.Current.Value;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
key = null;
|
|
||||||
next = null;
|
|
||||||
Reset();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Reset()
|
|
||||||
{
|
|
||||||
_enumerator = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
namespace Upsilon.BaseTypes
|
namespace Upsilon.BaseTypes
|
||||||
{
|
{
|
||||||
public abstract class LuaType
|
public abstract class ScriptType
|
||||||
{
|
{
|
||||||
public abstract Type Type { get; }
|
public abstract Type Type { get; }
|
||||||
public abstract object ToCSharpObject();
|
public abstract object ToCSharpObject();
|
|
@ -0,0 +1,9 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Upsilon.BaseTypes.ScriptTypeInterfaces
|
||||||
|
{
|
||||||
|
internal interface IIterable
|
||||||
|
{
|
||||||
|
IEnumerator<(string Key, ScriptType value)> GetEnumerator();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
using Upsilon.Evaluator;
|
using Upsilon.Evaluator;
|
||||||
|
|
||||||
namespace Upsilon.BaseTypes.LuaTypeInterfaces
|
namespace Upsilon.BaseTypes.ScriptTypeInterfaces
|
||||||
{
|
{
|
||||||
internal interface IScopeOwner
|
internal interface IScopeOwner
|
||||||
{
|
{
|
|
@ -1,32 +1,33 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Upsilon.BaseTypes.ScriptTypeInterfaces;
|
||||||
using Upsilon.Evaluator;
|
using Upsilon.Evaluator;
|
||||||
using Upsilon.Text;
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.BaseTypes
|
namespace Upsilon.BaseTypes
|
||||||
{
|
{
|
||||||
internal class SimpleLuaTable : LuaType, IIndexable
|
internal class SimpleScriptTable : ScriptType, IIndexable
|
||||||
{
|
{
|
||||||
private readonly IList<LuaType> _objects;
|
private readonly IList<ScriptType> _objects;
|
||||||
|
|
||||||
public SimpleLuaTable(IList<LuaType> objects)
|
public SimpleScriptTable(IList<ScriptType> objects)
|
||||||
{
|
{
|
||||||
_objects = 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;
|
int i;
|
||||||
switch (index.Type)
|
switch (index.Type)
|
||||||
{
|
{
|
||||||
case Type.String:
|
case Type.String:
|
||||||
{
|
{
|
||||||
var str = (LuaString)index;
|
var str = (ScriptString)index;
|
||||||
i = int.Parse(str.Value) - 1;
|
i = int.Parse(str.Value) - 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Type.Number:
|
case Type.Number:
|
||||||
{
|
{
|
||||||
var ind = (Number.NumberLong) index;
|
var ind = (Number.ScriptNumberLong) index;
|
||||||
i = (int) ind.Value - 1;
|
i = (int) ind.Value - 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -37,7 +38,7 @@ namespace Upsilon.BaseTypes
|
||||||
return _objects[i];
|
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();
|
throw new System.NotImplementedException();
|
||||||
}
|
}
|
|
@ -10,6 +10,6 @@ namespace Upsilon.BaseTypes
|
||||||
Function,
|
Function,
|
||||||
UserData,
|
UserData,
|
||||||
Thread,
|
Thread,
|
||||||
Table
|
Table,
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,31 +6,31 @@ namespace Upsilon.BaseTypes
|
||||||
{
|
{
|
||||||
internal static class TypeConversion
|
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)
|
switch (o)
|
||||||
{
|
{
|
||||||
case bool b:
|
case bool b:
|
||||||
return new LuaBoolean(b);
|
return new ScriptBoolean(b);
|
||||||
case int i:
|
case int i:
|
||||||
return new NumberLong(i);
|
return new ScriptNumberLong(i);
|
||||||
case long i:
|
case long i:
|
||||||
return new NumberLong(i);
|
return new ScriptNumberLong(i);
|
||||||
case float f:
|
case float f:
|
||||||
return new NumberDouble(f);
|
return new ScriptNumberDouble(f);
|
||||||
case double f:
|
case double f:
|
||||||
return new NumberDouble(f);
|
return new ScriptNumberDouble(f);
|
||||||
case string s:
|
case string s:
|
||||||
return new LuaString(s);
|
return new ScriptString(s);
|
||||||
case null:
|
case null:
|
||||||
return new LuaNull();
|
return new ScriptNull();
|
||||||
default:
|
default:
|
||||||
return ConvertUserData(o);
|
return ConvertUserData(o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LuaType ConvertUserData(object o)
|
private static ScriptType ConvertUserData(object o)
|
||||||
{
|
{
|
||||||
if (o is IList ls)
|
if (o is IList ls)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,7 @@ using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.BaseTypes.UserData
|
namespace Upsilon.BaseTypes.UserData
|
||||||
{
|
{
|
||||||
internal class DictionaryUserData : LuaType, IUserData
|
internal class DictionaryUserData : ScriptType, IUserData
|
||||||
{
|
{
|
||||||
public IDictionary Dictionary { get; }
|
public IDictionary Dictionary { get; }
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
Dictionary = dictionary;
|
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();
|
var key = index.ToCSharpObject();
|
||||||
if (Dictionary.Contains(key))
|
if (Dictionary.Contains(key))
|
||||||
|
@ -21,10 +21,10 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
return Dictionary[key].ToLuaType();
|
return Dictionary[key].ToLuaType();
|
||||||
}
|
}
|
||||||
//TODO: log error
|
//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();
|
var key = index.ToCSharpObject();
|
||||||
if (Dictionary.Contains(key))
|
if (Dictionary.Contains(key))
|
||||||
|
|
|
@ -3,7 +3,7 @@ using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.BaseTypes.UserData
|
namespace Upsilon.BaseTypes.UserData
|
||||||
{
|
{
|
||||||
internal class GenericUserData : LuaType, IUserData
|
internal class GenericUserData : ScriptType, IUserData
|
||||||
{
|
{
|
||||||
public GenericUserData(object dictionary)
|
public GenericUserData(object dictionary)
|
||||||
{
|
{
|
||||||
|
@ -25,7 +25,7 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
return Value.GetType();
|
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 s = index.ToCSharpObject().ToString();
|
||||||
var (type, failed, error) = _typeInfo.Get(Value, s);
|
var (type, failed, error) = _typeInfo.Get(Value, s);
|
||||||
|
@ -36,7 +36,7 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
return type;
|
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 s = index.ToCSharpObject().ToString();
|
||||||
var (failed, error) = _typeInfo.Set(Value, s, value);
|
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);
|
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);
|
return _typeInfo.UnaryOperator(Value, par1, op);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
using Upsilon.BaseTypes.ScriptTypeInterfaces;
|
||||||
|
|
||||||
namespace Upsilon.BaseTypes.UserData
|
namespace Upsilon.BaseTypes.UserData
|
||||||
{
|
{
|
||||||
internal interface IUserData : IIndexable
|
internal interface IUserData : IIndexable
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Upsilon.BaseTypes.ScriptTypeInterfaces;
|
||||||
using Upsilon.Evaluator;
|
using Upsilon.Evaluator;
|
||||||
using Upsilon.Text;
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.BaseTypes.UserData
|
namespace Upsilon.BaseTypes.UserData
|
||||||
{
|
{
|
||||||
internal class ListUserData : LuaType, IUserData
|
internal class ListUserData : ScriptType, IUserData, IIterable
|
||||||
{
|
{
|
||||||
private IList List { get; }
|
private IList List { get; }
|
||||||
|
|
||||||
|
@ -13,17 +15,17 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
List = list;
|
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;
|
int i;
|
||||||
if (index.Type == Type.String)
|
if (index.Type == Type.String)
|
||||||
{
|
{
|
||||||
var str = (LuaString)index;
|
var str = (ScriptString)index;
|
||||||
i = int.Parse(str.Value) - 1;
|
i = int.Parse(str.Value) - 1;
|
||||||
}
|
}
|
||||||
else if (index.Type == Type.Number)
|
else if (index.Type == Type.Number)
|
||||||
{
|
{
|
||||||
var ind = (Number.NumberLong) index;
|
var ind = (Number.ScriptNumberLong) index;
|
||||||
i = (int) ind.Value - 1;
|
i = (int) ind.Value - 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -33,7 +35,7 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
return List[i].ToLuaType();
|
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();
|
throw new System.NotImplementedException();
|
||||||
}
|
}
|
||||||
|
@ -48,5 +50,10 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
{
|
{
|
||||||
return List.GetType();
|
return List.GetType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerator<(string Key, ScriptType value)> GetEnumerator()
|
||||||
|
{
|
||||||
|
throw new System.NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -22,11 +22,11 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
{
|
{
|
||||||
public UserDataMethodParameter(ParameterInfo info)
|
public UserDataMethodParameter(ParameterInfo info)
|
||||||
{
|
{
|
||||||
TypeHash = info.ParameterType.GetHashCode();
|
Type = info.ParameterType;
|
||||||
IsOptional = info.IsOptional;
|
IsOptional = info.IsOptional;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int TypeHash { get; }
|
public System.Type Type { get; }
|
||||||
public bool IsOptional { get; }
|
public bool IsOptional { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,8 +62,9 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
valid = false;
|
valid = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
var parameterHash = parameterTypes[index].GetHashCode();
|
var parameter = parameterTypes[index];
|
||||||
if (userDataMethodParameter.TypeHash != parameterHash)
|
if (userDataMethodParameter.Type != parameter &&
|
||||||
|
!userDataMethodParameter.Type.IsAssignableFrom(parameter))
|
||||||
{
|
{
|
||||||
valid = false;
|
valid = false;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
private Dictionary<string, UserDataMethod> Methods { get; }
|
private Dictionary<string, UserDataMethod> Methods { get; }
|
||||||
private UserDataTypeOperators OperatorHandler { 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)
|
if (value.GetType() != Type)
|
||||||
return (null, true, "Invalid Type");
|
return (null, true, "Invalid Type");
|
||||||
|
@ -48,13 +48,13 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
}
|
}
|
||||||
if (Methods.TryGetValue(member, out var method))
|
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}'.");
|
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();
|
member = member.ToLowerInvariant();
|
||||||
if (value.GetType() != Type)
|
if (value.GetType() != Type)
|
||||||
|
@ -77,22 +77,22 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
return (true, $"Cannot find member '{member}' on type '{Type}'");
|
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());
|
var method = OperatorHandler.GetBinaryOperator(op, par1.GetCSharpType(), par2.GetCSharpType());
|
||||||
if (method == null)
|
if (method == null)
|
||||||
{
|
{
|
||||||
return (new LuaNull(), true);
|
return (new ScriptNull(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (method.Invoke(value, new[] {par1.ToCSharpObject(), par2.ToCSharpObject()}).ToLuaType(), false);
|
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());
|
var method = OperatorHandler.GetUnaryOperator(op, par1.GetCSharpType());
|
||||||
if (method == null)
|
if (method == null)
|
||||||
{
|
{
|
||||||
return (new LuaNull(), true);
|
return (new ScriptNull(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (method.Invoke(value, new[] {par1.ToCSharpObject()}).ToLuaType(), false);
|
return (method.Invoke(value, new[] {par1.ToCSharpObject()}).ToLuaType(), false);
|
||||||
|
|
|
@ -70,6 +70,9 @@ namespace Upsilon.Binder
|
||||||
return BindMultiAssignmentStatement((MultiAssignmentStatementSyntax) s);
|
return BindMultiAssignmentStatement((MultiAssignmentStatementSyntax) s);
|
||||||
case SyntaxKind.NumericForStatement:
|
case SyntaxKind.NumericForStatement:
|
||||||
return BindNumericForStatement((NumericForStatementSyntax) s);
|
return BindNumericForStatement((NumericForStatementSyntax) s);
|
||||||
|
case SyntaxKind.GenericForStatement:
|
||||||
|
return BindGenericForStatement((GenericForStatementSyntax) s);
|
||||||
|
|
||||||
case SyntaxKind.BreakStatement:
|
case SyntaxKind.BreakStatement:
|
||||||
return new BoundBreakStatement();
|
return new BoundBreakStatement();
|
||||||
}
|
}
|
||||||
|
@ -140,23 +143,23 @@ namespace Upsilon.Binder
|
||||||
private BoundExpression BindLiteralExpression(LiteralExpressionSyntax e)
|
private BoundExpression BindLiteralExpression(LiteralExpressionSyntax e)
|
||||||
{
|
{
|
||||||
var value = e.Value;
|
var value = e.Value;
|
||||||
LuaType outValue = null;
|
ScriptType outValue = null;
|
||||||
switch (value)
|
switch (value)
|
||||||
{
|
{
|
||||||
case double d:
|
case double d:
|
||||||
outValue = new NumberDouble(d);
|
outValue = new ScriptNumberDouble(d);
|
||||||
break;
|
break;
|
||||||
case long l:
|
case long l:
|
||||||
outValue = new NumberLong(l);
|
outValue = new ScriptNumberLong(l);
|
||||||
break;
|
break;
|
||||||
case bool b:
|
case bool b:
|
||||||
outValue = new LuaBoolean(b);
|
outValue = new ScriptBoolean(b);
|
||||||
break;
|
break;
|
||||||
case string s:
|
case string s:
|
||||||
outValue = new LuaString(s);
|
outValue = new ScriptString(s);
|
||||||
break;
|
break;
|
||||||
case null:
|
case null:
|
||||||
outValue = new LuaNull();
|
outValue = new ScriptNull();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -221,7 +224,7 @@ namespace Upsilon.Binder
|
||||||
if (!Scope.TryGetVariable(name, true, out var variable))
|
if (!Scope.TryGetVariable(name, true, out var variable))
|
||||||
{
|
{
|
||||||
_diagnostics.LogUnknownVariable(e.Identifier.Span, name);
|
_diagnostics.LogUnknownVariable(e.Identifier.Span, name);
|
||||||
return new BoundLiteralExpression(new LuaNull());
|
return new BoundLiteralExpression(new ScriptNull());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BoundVariableExpression(variable);
|
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)
|
private BoundStatement BindMultiAssignmentStatement(MultiAssignmentStatementSyntax s)
|
||||||
|
@ -430,7 +433,7 @@ namespace Upsilon.Binder
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_diagnostics.LogCannotConvert(Type.Function, variable.Type, e.Span);
|
_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)
|
if (index.Type != Type.Number && index.Type != Type.String && index.Type != Type.Unknown)
|
||||||
{
|
{
|
||||||
_diagnostics.LogInvalidIndexExpression(expression.Type, index.Type, e.Span);
|
_diagnostics.LogInvalidIndexExpression(expression.Type, index.Type, e.Span);
|
||||||
return new BoundLiteralExpression(new LuaNull());
|
return new BoundLiteralExpression(new ScriptNull());
|
||||||
}
|
}
|
||||||
switch (expression.Type)
|
switch (expression.Type)
|
||||||
{
|
{
|
||||||
|
@ -486,7 +489,7 @@ namespace Upsilon.Binder
|
||||||
return new BoundIndexExpression(expression, index, Type.String);
|
return new BoundIndexExpression(expression, index, Type.String);
|
||||||
default:
|
default:
|
||||||
_diagnostics.LogInvalidIndexExpression(expression.Type, index.Type, e.Span);
|
_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);
|
return new BoundFullStopIndexExpression(expression, index);
|
||||||
default:
|
default:
|
||||||
_diagnostics.LogInvalidIndexExpression(expression.Type, Type.String, e.Span);
|
_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);
|
Scope = new BoundScope(Scope);
|
||||||
var variable = new VariableSymbol(variableName, Type.Number, true);
|
var variable = new VariableSymbol(variableName, Type.Number, true);
|
||||||
Scope.SetVariable(variable);
|
Scope.SetVariable(variable);
|
||||||
var boundStart = BindExpression(e.StartExpression);
|
var boundStart = BindExpression(e.StartExpression);
|
||||||
var boundStop = BindExpression(e.StopExpression);
|
var boundStop = BindExpression(e.StopExpression);
|
||||||
BoundExpression boundStep = null;
|
BoundExpression boundStep = null;
|
||||||
if (e.StepExpression != null)
|
if (e.StepExpression != null)
|
||||||
boundStep = BindExpression(e.StepExpression);
|
boundStep = BindExpression(e.StepExpression);
|
||||||
var block = BindBlockStatement((BlockStatementSyntax) e.Block);
|
var block = BindBlockStatement((BlockStatementSyntax) e.Block);
|
||||||
Scope = Scope.ParentScope;
|
Scope = Scope.ParentScope;
|
||||||
return new BoundNumericForStatement(variable, boundStart, boundStop, boundStep, (BoundBlockStatement) block);
|
return new BoundNumericForStatement(variable, boundStart, boundStop, boundStep, (BoundBlockStatement) block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BoundStatement BindGenericForStatement(GenericForStatementSyntax e)
|
||||||
|
{
|
||||||
|
Scope = new BoundScope(Scope);
|
||||||
|
var array = ImmutableArray.CreateBuilder<VariableSymbol>();
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,13 +4,13 @@ namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
internal class BoundLiteralExpression : BoundExpression
|
internal class BoundLiteralExpression : BoundExpression
|
||||||
{
|
{
|
||||||
public BoundLiteralExpression(LuaType value)
|
public BoundLiteralExpression(ScriptType value)
|
||||||
{
|
{
|
||||||
Value = value;
|
Value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundLiteralExpression;
|
public override BoundKind Kind => BoundKind.BoundLiteralExpression;
|
||||||
public override Type Type => Value.Type;
|
public override Type Type => Value.Type;
|
||||||
public LuaType Value { get; }
|
public ScriptType Value { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -26,6 +26,7 @@ namespace Upsilon.Binder
|
||||||
BoundFullstopIndexExpression,
|
BoundFullstopIndexExpression,
|
||||||
BoundMultiAssignmentStatement,
|
BoundMultiAssignmentStatement,
|
||||||
BoundNumericForStatement,
|
BoundNumericForStatement,
|
||||||
BoundBreakStatement
|
BoundGenericForStatement,
|
||||||
|
BoundBreakStatement,
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
|
||||||
|
namespace Upsilon.Binder
|
||||||
|
{
|
||||||
|
public class BoundGenericForStatement : BoundStatement
|
||||||
|
{
|
||||||
|
public ImmutableArray<VariableSymbol> Variables { get; }
|
||||||
|
public BoundExpression BoundEnumerableExpression { get; }
|
||||||
|
public BoundStatement Block { get; }
|
||||||
|
|
||||||
|
public BoundGenericForStatement(ImmutableArray<VariableSymbol> variables,
|
||||||
|
BoundExpression boundEnumerableExpression, BoundStatement block)
|
||||||
|
{
|
||||||
|
Variables = variables;
|
||||||
|
BoundEnumerableExpression = boundEnumerableExpression;
|
||||||
|
Block = block;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override BoundKind Kind => BoundKind.BoundGenericForStatement;
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,32 +9,32 @@ namespace Upsilon.Evaluator
|
||||||
private readonly EvaluationScope _parentScope;
|
private readonly EvaluationScope _parentScope;
|
||||||
private EvaluationScope _getOnlyParentScope;
|
private EvaluationScope _getOnlyParentScope;
|
||||||
|
|
||||||
public readonly Dictionary<string, LuaType> Variables;
|
public readonly Dictionary<string, ScriptType> Variables;
|
||||||
private readonly Dictionary<string, LuaType> _localVariables;
|
private readonly Dictionary<string, ScriptType> _localVariables;
|
||||||
|
|
||||||
|
|
||||||
internal EvaluationScope(EvaluationScope parentScope)
|
internal EvaluationScope(EvaluationScope parentScope)
|
||||||
{
|
{
|
||||||
_parentScope = parentScope;
|
_parentScope = parentScope;
|
||||||
Variables = new Dictionary<string, LuaType>();
|
Variables = new Dictionary<string, ScriptType>();
|
||||||
_localVariables = new Dictionary<string, LuaType>();
|
_localVariables = new Dictionary<string, ScriptType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal EvaluationScope(Dictionary<string, LuaType> vars)
|
internal EvaluationScope(Dictionary<string, ScriptType> vars)
|
||||||
{
|
{
|
||||||
Variables = vars;
|
Variables = vars;
|
||||||
_localVariables = new Dictionary<string, LuaType>();
|
_localVariables = new Dictionary<string, ScriptType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static EvaluationScope CreateWithGetOnlyParent(EvaluationScope parent)
|
internal static EvaluationScope CreateWithGetOnlyParent(EvaluationScope parent)
|
||||||
{
|
{
|
||||||
var scope = new EvaluationScope(new Dictionary<string, LuaType>()) {_getOnlyParentScope = parent};
|
var scope = new EvaluationScope(new Dictionary<string, ScriptType>()) {_getOnlyParentScope = parent};
|
||||||
return scope;
|
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))
|
if (_localVariables.ContainsKey(symbol.Name))
|
||||||
{
|
{
|
||||||
|
@ -51,6 +51,14 @@ namespace Upsilon.Evaluator
|
||||||
{
|
{
|
||||||
Variables[symbol.Name] = obj;
|
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
|
else
|
||||||
{
|
{
|
||||||
Variables.Add(symbol.Name, obj);
|
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)
|
if (_parentScope != null)
|
||||||
_parentScope.SetGlobal(symbol, obj);
|
_parentScope.SetGlobal(symbol, obj);
|
||||||
else
|
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))
|
if (_localVariables.TryGetValue(symbol.Name, out obj))
|
||||||
return true;
|
return true;
|
||||||
|
@ -84,7 +92,7 @@ namespace Upsilon.Evaluator
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGet(string variable, out LuaType obj)
|
public bool TryGet(string variable, out ScriptType obj)
|
||||||
{
|
{
|
||||||
if (_localVariables.TryGetValue(variable, out obj))
|
if (_localVariables.TryGetValue(variable, out obj))
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -2,8 +2,8 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using Upsilon.BaseTypes;
|
using Upsilon.BaseTypes;
|
||||||
using Upsilon.BaseTypes.LuaTypeInterfaces;
|
|
||||||
using Upsilon.BaseTypes.Number;
|
using Upsilon.BaseTypes.Number;
|
||||||
|
using Upsilon.BaseTypes.ScriptTypeInterfaces;
|
||||||
using Upsilon.BaseTypes.UserData;
|
using Upsilon.BaseTypes.UserData;
|
||||||
using Upsilon.Binder;
|
using Upsilon.Binder;
|
||||||
using Type = Upsilon.BaseTypes.Type;
|
using Type = Upsilon.BaseTypes.Type;
|
||||||
|
@ -13,13 +13,13 @@ namespace Upsilon.Evaluator
|
||||||
internal class Evaluator
|
internal class Evaluator
|
||||||
{
|
{
|
||||||
private Diagnostics _diagnostics;
|
private Diagnostics _diagnostics;
|
||||||
private LuaType _lastValue;
|
private ScriptType _lastValue;
|
||||||
private LuaType _returnValue;
|
private ScriptType _returnValue;
|
||||||
internal EvaluationScope Scope { get; private set; }
|
internal EvaluationScope Scope { get; private set; }
|
||||||
private bool HasReturned { get; set; }
|
private bool HasReturned { get; set; }
|
||||||
private bool HasBroken { get; set; }
|
private bool HasBroken { get; set; }
|
||||||
|
|
||||||
internal Evaluator(Diagnostics diagnostics, Dictionary<string, LuaType> variables)
|
internal Evaluator(Diagnostics diagnostics, Dictionary<string, ScriptType> variables)
|
||||||
{
|
{
|
||||||
_diagnostics = diagnostics;
|
_diagnostics = diagnostics;
|
||||||
Scope = new EvaluationScope(variables);
|
Scope = new EvaluationScope(variables);
|
||||||
|
@ -38,7 +38,7 @@ namespace Upsilon.Evaluator
|
||||||
return new Evaluator {_diagnostics = diagnostics, Scope = scope};
|
return new Evaluator {_diagnostics = diagnostics, Scope = scope};
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaType Evaluate(BoundScript e)
|
public ScriptType Evaluate(BoundScript e)
|
||||||
{
|
{
|
||||||
EvaluateNode(e.Statement);
|
EvaluateNode(e.Statement);
|
||||||
if (_returnValue == null)
|
if (_returnValue == null)
|
||||||
|
@ -46,27 +46,27 @@ namespace Upsilon.Evaluator
|
||||||
return _returnValue;
|
return _returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaType Evaluate(BoundScript e, string functionName, ImmutableArray<LuaType> parameters)
|
public ScriptType Evaluate(BoundScript e, string functionName, ImmutableArray<ScriptType> parameters)
|
||||||
{
|
{
|
||||||
EvaluateNode(e.Statement);
|
EvaluateNode(e.Statement);
|
||||||
if (!Scope.TryGet(functionName, out var statement) || statement.Type != Type.Function)
|
if (!Scope.TryGet(functionName, out var statement) || statement.Type != Type.Function)
|
||||||
{
|
{
|
||||||
throw new ArgumentException(($"Function '{functionName}' could not be found"));
|
throw new ArgumentException(($"Function '{functionName}' could not be found"));
|
||||||
}
|
}
|
||||||
var function = (LuaInternalFunction) statement;
|
var function = (ScriptInternalFunction) statement;
|
||||||
var innerEvaluator = new Evaluator(_diagnostics, Scope);
|
var innerEvaluator = new Evaluator(_diagnostics, Scope);
|
||||||
for (var index = 0; index < parameters.Length; index++)
|
for (var index = 0; index < parameters.Length; index++)
|
||||||
{
|
{
|
||||||
var parameter = parameters[index];
|
var parameter = parameters[index];
|
||||||
var parameterName = function.Parameters[index];
|
var parameterName = function.Parameters[index];
|
||||||
innerEvaluator.Scope.Set(parameterName, parameter);
|
innerEvaluator.Scope.Set(parameterName, parameter, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = innerEvaluator.EvaluateNode(function.Block);
|
var result = innerEvaluator.EvaluateNode(function.Block);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal LuaType EvaluateNode(BoundNode b)
|
internal ScriptType EvaluateNode(BoundNode b)
|
||||||
{
|
{
|
||||||
switch (b.Kind)
|
switch (b.Kind)
|
||||||
{
|
{
|
||||||
|
@ -95,6 +95,8 @@ namespace Upsilon.Evaluator
|
||||||
case BoundKind.BoundTableAssigmentStatement:
|
case BoundKind.BoundTableAssigmentStatement:
|
||||||
case BoundKind.BoundMultiAssignmentStatement:
|
case BoundKind.BoundMultiAssignmentStatement:
|
||||||
case BoundKind.BoundNumericForStatement:
|
case BoundKind.BoundNumericForStatement:
|
||||||
|
case BoundKind.BoundGenericForStatement:
|
||||||
|
case BoundKind.BoundBreakStatement:
|
||||||
EvaluateStatement((BoundStatement) b);
|
EvaluateStatement((BoundStatement) b);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -136,6 +138,9 @@ namespace Upsilon.Evaluator
|
||||||
case BoundKind.BoundBreakStatement:
|
case BoundKind.BoundBreakStatement:
|
||||||
HasBroken = true;
|
HasBroken = true;
|
||||||
return;
|
return;
|
||||||
|
case BoundKind.BoundGenericForStatement:
|
||||||
|
EvaluateGenericForStatement((BoundGenericForStatement) e);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
EvaluateExpressionStatement((BoundExpressionStatement) e);
|
EvaluateExpressionStatement((BoundExpressionStatement) e);
|
||||||
break;
|
break;
|
||||||
|
@ -148,7 +153,7 @@ namespace Upsilon.Evaluator
|
||||||
_lastValue = EvaluateExpression(e.Expression);
|
_lastValue = EvaluateExpression(e.Expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal LuaType EvaluateExpression(BoundExpression e)
|
internal ScriptType EvaluateExpression(BoundExpression e)
|
||||||
{
|
{
|
||||||
switch (e.Kind)
|
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);
|
var operand = EvaluateExpression(e.InExpression);
|
||||||
switch (e.Operator.Kind)
|
switch (e.Operator.Kind)
|
||||||
|
@ -186,7 +191,7 @@ namespace Upsilon.Evaluator
|
||||||
return operand;
|
return operand;
|
||||||
case BoundUnaryOperator.OperatorKind.Negation:
|
case BoundUnaryOperator.OperatorKind.Negation:
|
||||||
if (operand.Type == Type.Number)
|
if (operand.Type == Type.Number)
|
||||||
return -((Number)operand);
|
return -((ScriptNumber)operand);
|
||||||
else if (operand.Type == Type.UserData)
|
else if (operand.Type == Type.UserData)
|
||||||
{
|
{
|
||||||
var ud = (GenericUserData) operand;
|
var ud = (GenericUserData) operand;
|
||||||
|
@ -197,7 +202,7 @@ namespace Upsilon.Evaluator
|
||||||
goto default;
|
goto default;
|
||||||
case BoundUnaryOperator.OperatorKind.LogicalNegation:
|
case BoundUnaryOperator.OperatorKind.LogicalNegation:
|
||||||
if (operand.Type == Type.Boolean)
|
if (operand.Type == Type.Boolean)
|
||||||
return !(LuaBoolean) operand;
|
return !(ScriptBoolean) operand;
|
||||||
else if (operand.Type == Type.UserData)
|
else if (operand.Type == Type.UserData)
|
||||||
{
|
{
|
||||||
var ud = (GenericUserData) operand;
|
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 left = EvaluateExpression(e.LeftExpression);
|
||||||
var right = EvaluateExpression(e.RightExpression);
|
var right = EvaluateExpression(e.RightExpression);
|
||||||
|
@ -220,10 +225,16 @@ namespace Upsilon.Evaluator
|
||||||
{
|
{
|
||||||
case BoundBinaryOperator.OperatorKind.Addition:
|
case BoundBinaryOperator.OperatorKind.Addition:
|
||||||
if (left.Type == Type.Number)
|
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)
|
else if (left.Type == Type.String)
|
||||||
{
|
{
|
||||||
return ((LuaString) left) + right;
|
return ((ScriptString) left) + right;
|
||||||
}
|
}
|
||||||
else if (left.Type == Type.UserData)
|
else if (left.Type == Type.UserData)
|
||||||
{
|
{
|
||||||
|
@ -236,7 +247,7 @@ namespace Upsilon.Evaluator
|
||||||
case BoundBinaryOperator.OperatorKind.Subtraction:
|
case BoundBinaryOperator.OperatorKind.Subtraction:
|
||||||
if (left.Type == Type.Number)
|
if (left.Type == Type.Number)
|
||||||
{
|
{
|
||||||
return ((Number)left) - ((Number)right);
|
return ((ScriptNumber)left) - ((ScriptNumber)right);
|
||||||
}
|
}
|
||||||
else if (left.Type == Type.UserData)
|
else if (left.Type == Type.UserData)
|
||||||
{
|
{
|
||||||
|
@ -249,7 +260,7 @@ namespace Upsilon.Evaluator
|
||||||
case BoundBinaryOperator.OperatorKind.Multiplication:
|
case BoundBinaryOperator.OperatorKind.Multiplication:
|
||||||
if (left.Type == Type.Number)
|
if (left.Type == Type.Number)
|
||||||
{
|
{
|
||||||
return ((Number)left) * ((Number)right);
|
return ((ScriptNumber)left) * ((ScriptNumber)right);
|
||||||
}
|
}
|
||||||
else if (left.Type == Type.UserData)
|
else if (left.Type == Type.UserData)
|
||||||
{
|
{
|
||||||
|
@ -262,7 +273,7 @@ namespace Upsilon.Evaluator
|
||||||
case BoundBinaryOperator.OperatorKind.Division:
|
case BoundBinaryOperator.OperatorKind.Division:
|
||||||
if (left.Type == Type.Number)
|
if (left.Type == Type.Number)
|
||||||
{
|
{
|
||||||
return ((Number)left) / ((Number)right);
|
return ((ScriptNumber)left) / ((ScriptNumber)right);
|
||||||
}
|
}
|
||||||
else if (left.Type == Type.UserData)
|
else if (left.Type == Type.UserData)
|
||||||
{
|
{
|
||||||
|
@ -273,9 +284,9 @@ namespace Upsilon.Evaluator
|
||||||
}
|
}
|
||||||
goto default;
|
goto default;
|
||||||
case BoundBinaryOperator.OperatorKind.Equality:
|
case BoundBinaryOperator.OperatorKind.Equality:
|
||||||
return new LuaBoolean(Equals(left, right));
|
return new ScriptBoolean(Equals(left, right));
|
||||||
case BoundBinaryOperator.OperatorKind.Inequality:
|
case BoundBinaryOperator.OperatorKind.Inequality:
|
||||||
return new LuaBoolean(!Equals(left, right));
|
return new ScriptBoolean(!Equals(left, right));
|
||||||
default:
|
default:
|
||||||
throw new Exception("Invalid Binary Operator: " + e.Operator);
|
throw new Exception("Invalid Binary Operator: " + e.Operator);
|
||||||
}
|
}
|
||||||
|
@ -286,7 +297,7 @@ namespace Upsilon.Evaluator
|
||||||
var val = EvaluateExpression(e.BoundExpression);
|
var val = EvaluateExpression(e.BoundExpression);
|
||||||
if (e.Variable.Local)
|
if (e.Variable.Local)
|
||||||
{
|
{
|
||||||
Scope.Set(e.Variable, val);
|
Scope.Set(e.Variable, val, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -307,9 +318,9 @@ namespace Upsilon.Evaluator
|
||||||
continue;
|
continue;
|
||||||
if (variableSymbol.Name == "_")
|
if (variableSymbol.Name == "_")
|
||||||
continue;
|
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)
|
if (variableSymbol.Local)
|
||||||
Scope.Set(variableSymbol, value);
|
Scope.Set(variableSymbol, value, true);
|
||||||
else
|
else
|
||||||
Scope.SetGlobal(variableSymbol, value);
|
Scope.SetGlobal(variableSymbol, value);
|
||||||
}
|
}
|
||||||
|
@ -321,7 +332,7 @@ namespace Upsilon.Evaluator
|
||||||
_lastValue = val;
|
_lastValue = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
private LuaType EvaluateVariableExpression(BoundVariableExpression e)
|
private ScriptType EvaluateVariableExpression(BoundVariableExpression e)
|
||||||
{
|
{
|
||||||
if (Scope.TryGet(e.Variable, out var val))
|
if (Scope.TryGet(e.Variable, out var val))
|
||||||
{
|
{
|
||||||
|
@ -345,7 +356,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 ((LuaBoolean) condition)
|
if ((ScriptBoolean) condition)
|
||||||
{
|
{
|
||||||
EvaluateStatement(boundBlockStatement.Block);
|
EvaluateStatement(boundBlockStatement.Block);
|
||||||
}
|
}
|
||||||
|
@ -363,31 +374,31 @@ namespace Upsilon.Evaluator
|
||||||
{
|
{
|
||||||
var func = EvaluateBoundFunctionStatement(e.Func);
|
var func = EvaluateBoundFunctionStatement(e.Func);
|
||||||
if (e.Variable.Local)
|
if (e.Variable.Local)
|
||||||
Scope.Set(e.Variable, func);
|
Scope.Set(e.Variable, func, true);
|
||||||
else
|
else
|
||||||
Scope.SetGlobal(e.Variable, func);
|
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;
|
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;
|
return func;
|
||||||
}
|
}
|
||||||
|
|
||||||
private LuaType EvaluateBoundFunctionCallExpression(BoundFunctionCallExpression boundFunctionCallExpression)
|
private ScriptType EvaluateBoundFunctionCallExpression(BoundFunctionCallExpression boundFunctionCallExpression)
|
||||||
{
|
{
|
||||||
var variable = EvaluateExpression(boundFunctionCallExpression.Identifier);
|
var variable = EvaluateExpression(boundFunctionCallExpression.Identifier);
|
||||||
if (!(variable is LuaFunction function))
|
if (!(variable is ScriptFunction function))
|
||||||
{
|
{
|
||||||
throw new Exception($"Variable is not a function.");
|
throw new Exception($"Variable is not a function.");
|
||||||
}
|
}
|
||||||
var ls = new List<LuaType>();
|
var ls = new List<ScriptType>();
|
||||||
foreach (var t in boundFunctionCallExpression.Parameters)
|
foreach (var t in boundFunctionCallExpression.Parameters)
|
||||||
{
|
{
|
||||||
var evaluate = EvaluateExpression(t);
|
var evaluate = EvaluateExpression(t);
|
||||||
|
@ -405,7 +416,7 @@ namespace Upsilon.Evaluator
|
||||||
HasReturned = true;
|
HasReturned = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private LuaType EvaluateTableExpression(BoundTableExpression e)
|
private ScriptType EvaluateTableExpression(BoundTableExpression e)
|
||||||
{
|
{
|
||||||
var tableScope = EvaluationScope.CreateWithGetOnlyParent(Scope);
|
var tableScope = EvaluationScope.CreateWithGetOnlyParent(Scope);
|
||||||
var innerEvaluator = new Evaluator(_diagnostics, tableScope);
|
var innerEvaluator = new Evaluator(_diagnostics, tableScope);
|
||||||
|
@ -424,7 +435,7 @@ namespace Upsilon.Evaluator
|
||||||
innerEvaluator.EvaluateStatement(boundStatement);
|
innerEvaluator.EvaluateStatement(boundStatement);
|
||||||
if (innerEvaluator._lastValue != null)
|
if (innerEvaluator._lastValue != null)
|
||||||
tableScope.Set(new VariableSymbol(currentPos.ToString(), innerEvaluator._lastValue.Type, false),
|
tableScope.Set(new VariableSymbol(currentPos.ToString(), innerEvaluator._lastValue.Type, false),
|
||||||
innerEvaluator._lastValue);
|
innerEvaluator._lastValue, true);
|
||||||
innerEvaluator._lastValue = null;
|
innerEvaluator._lastValue = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -432,10 +443,10 @@ namespace Upsilon.Evaluator
|
||||||
|
|
||||||
currentPos++;
|
currentPos++;
|
||||||
}
|
}
|
||||||
return new LuaTable(tableScope);
|
return new ScriptTable(tableScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
private LuaType EvaluateIndexExpression(BoundIndexExpression e)
|
private ScriptType EvaluateIndexExpression(BoundIndexExpression e)
|
||||||
{
|
{
|
||||||
var variable = EvaluateExpression(e.Identifier);
|
var variable = EvaluateExpression(e.Identifier);
|
||||||
if (!(variable is IIndexable indexable))
|
if (!(variable is IIndexable indexable))
|
||||||
|
@ -451,7 +462,7 @@ namespace Upsilon.Evaluator
|
||||||
var indexer = EvaluateExpression(e.Index);
|
var indexer = EvaluateExpression(e.Index);
|
||||||
return indexable.Get(_diagnostics, e.Span, indexer, scope);
|
return indexable.Get(_diagnostics, e.Span, indexer, scope);
|
||||||
}
|
}
|
||||||
private LuaType EvaluateFullStopIndexExpression(BoundFullStopIndexExpression e)
|
private ScriptType EvaluateFullStopIndexExpression(BoundFullStopIndexExpression e)
|
||||||
{
|
{
|
||||||
var variable = EvaluateExpression(e.Expression);
|
var variable = EvaluateExpression(e.Expression);
|
||||||
if (!(variable is IIndexable indexable))
|
if (!(variable is IIndexable indexable))
|
||||||
|
@ -470,8 +481,8 @@ namespace Upsilon.Evaluator
|
||||||
|
|
||||||
private void EvaluateTableAssignmentStatement(BoundTableAssigmentStatement e)
|
private void EvaluateTableAssignmentStatement(BoundTableAssigmentStatement e)
|
||||||
{
|
{
|
||||||
LuaType table;
|
ScriptType table;
|
||||||
LuaType index;
|
ScriptType index;
|
||||||
if (e.TableIndexExpression.Kind == BoundKind.BoundIndexExpression)
|
if (e.TableIndexExpression.Kind == BoundKind.BoundIndexExpression)
|
||||||
{
|
{
|
||||||
table = EvaluateExpression(((BoundIndexExpression)e.TableIndexExpression).Identifier);
|
table = EvaluateExpression(((BoundIndexExpression)e.TableIndexExpression).Identifier);
|
||||||
|
@ -494,13 +505,13 @@ namespace Upsilon.Evaluator
|
||||||
private void EvaluateNumericForStatement(BoundNumericForStatement e)
|
private void EvaluateNumericForStatement(BoundNumericForStatement e)
|
||||||
{
|
{
|
||||||
var innerEvaluator = new Evaluator(_diagnostics, Scope);
|
var innerEvaluator = new Evaluator(_diagnostics, Scope);
|
||||||
var startVal = (NumberLong)innerEvaluator.EvaluateExpression(e.BoundStart);
|
var startVal = (ScriptNumberLong)innerEvaluator.EvaluateExpression(e.BoundStart);
|
||||||
innerEvaluator.Scope.Set(e.Variable, startVal);
|
innerEvaluator.Scope.Set(e.Variable, startVal, true);
|
||||||
var stopVal = (NumberLong)innerEvaluator.EvaluateExpression(e.BoundStop);
|
var stopVal = (ScriptNumberLong)innerEvaluator.EvaluateExpression(e.BoundStop);
|
||||||
long step = 1;
|
long step = 1;
|
||||||
if (e.BoundStep != null)
|
if (e.BoundStep != null)
|
||||||
{
|
{
|
||||||
var stepVal = (NumberLong)innerEvaluator.EvaluateExpression(e.BoundStep);
|
var stepVal = (ScriptNumberLong)innerEvaluator.EvaluateExpression(e.BoundStep);
|
||||||
step = stepVal.Value;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -64,7 +64,7 @@ namespace Upsilon.Evaluator
|
||||||
|
|
||||||
public object EvaluateFunction(string functionName, object[] parameters = null)
|
public object EvaluateFunction(string functionName, object[] parameters = null)
|
||||||
{
|
{
|
||||||
var luaParameters = ImmutableArray.CreateBuilder<LuaType>();
|
var luaParameters = ImmutableArray.CreateBuilder<ScriptType>();
|
||||||
if (parameters != null)
|
if (parameters != null)
|
||||||
{
|
{
|
||||||
foreach (var parameter in parameters)
|
foreach (var parameter in parameters)
|
||||||
|
@ -75,7 +75,7 @@ namespace Upsilon.Evaluator
|
||||||
return Convert(Evaluator.Evaluate(Bind(), functionName, luaParameters.ToImmutable()));
|
return Convert(Evaluator.Evaluate(Bind(), functionName, luaParameters.ToImmutable()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static T Convert<T>(LuaType t)
|
private static T Convert<T>(ScriptType t)
|
||||||
{
|
{
|
||||||
if (typeof(T) == typeof(double))
|
if (typeof(T) == typeof(double))
|
||||||
return (T)(object)System.Convert.ToDouble(t.ToCSharpObject());
|
return (T)(object)System.Convert.ToDouble(t.ToCSharpObject());
|
||||||
|
@ -84,7 +84,7 @@ namespace Upsilon.Evaluator
|
||||||
return (T) t.ToCSharpObject();
|
return (T) t.ToCSharpObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static object Convert(LuaType t)
|
private static object Convert(ScriptType t)
|
||||||
{
|
{
|
||||||
return t?.ToCSharpObject();
|
return t?.ToCSharpObject();
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ namespace Upsilon.Evaluator
|
||||||
|
|
||||||
public T EvaluateFunction<T>(string functionName, object[] parameters = null)
|
public T EvaluateFunction<T>(string functionName, object[] parameters = null)
|
||||||
{
|
{
|
||||||
var luaParameters = ImmutableArray.CreateBuilder<LuaType>();
|
var luaParameters = ImmutableArray.CreateBuilder<ScriptType>();
|
||||||
if (parameters != null)
|
if (parameters != null)
|
||||||
{
|
{
|
||||||
foreach (var parameter in parameters)
|
foreach (var parameter in parameters)
|
||||||
|
|
|
@ -166,13 +166,29 @@ namespace Upsilon.Parser
|
||||||
var doToken = MatchToken(SyntaxKind.DoKeyword);
|
var doToken = MatchToken(SyntaxKind.DoKeyword);
|
||||||
var block = ParseBlockStatement(new []{SyntaxKind.EndKeyword});
|
var block = ParseBlockStatement(new []{SyntaxKind.EndKeyword});
|
||||||
var endToken = MatchToken(SyntaxKind.EndKeyword);
|
var endToken = MatchToken(SyntaxKind.EndKeyword);
|
||||||
return new NumericForStatementSyntax(forToken, identifier, equals, v1, comma1, v2, comma2, v3, doToken,
|
return new NumericForStatementSyntax(forToken, identifier, equals, v1, comma1,
|
||||||
block, endToken);
|
v2, comma2, v3, doToken, block, endToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private StatementSyntax ParseGenericForStatement(SyntaxToken forToken)
|
private StatementSyntax ParseGenericForStatement(SyntaxToken forToken)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
var arr = ImmutableArray.CreateBuilder<IdentifierToken>();
|
||||||
|
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()
|
private ExpressionSyntax ParseFunctionExpression()
|
||||||
|
|
|
@ -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<IdentifierToken> 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<IdentifierToken> 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<SyntaxNode> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -78,6 +78,7 @@ namespace Upsilon.Parser
|
||||||
FunctionAssignmentStatement,
|
FunctionAssignmentStatement,
|
||||||
TableAssignmentStatement,
|
TableAssignmentStatement,
|
||||||
NumericForStatement,
|
NumericForStatement,
|
||||||
BreakStatement
|
BreakStatement,
|
||||||
|
GenericForStatement
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Upsilon.BaseTypes;
|
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 UnusedMember.Global
|
||||||
// ReSharper disable MemberCanBePrivate.Global
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
@ -25,15 +27,29 @@ namespace Upsilon.StandardLibraries
|
||||||
throw new Exception(message);
|
throw new Exception(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
[LuaFunction("ipairs")]
|
[LuaFunction("ipairs")]
|
||||||
public LuaType Pairs(IIterable table)
|
public ScriptType Pairs(IIterable table)
|
||||||
{
|
{
|
||||||
if (!table.Next(out var key, out var next))
|
if (!table.Next(out var key, out var next))
|
||||||
{
|
{
|
||||||
return new LuaNull();
|
return new ScriptNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new SimpleLuaTable(new List<LuaType>() {key, next});
|
return new SimpleScriptTable(new List<ScriptType>() {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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,16 +7,16 @@ namespace Upsilon.StandardLibraries
|
||||||
{
|
{
|
||||||
internal abstract class LuaLibrary
|
internal abstract class LuaLibrary
|
||||||
{
|
{
|
||||||
public Dictionary<string, LuaFunction> LoadMethods()
|
public Dictionary<string, ScriptFunction> LoadMethods()
|
||||||
{
|
{
|
||||||
var dictionary = new Dictionary<string, LuaFunction>();
|
var dictionary = new Dictionary<string, ScriptFunction>();
|
||||||
var methods = GetType().GetMethods();
|
var methods = GetType().GetMethods();
|
||||||
foreach (var methodInfo in methods)
|
foreach (var methodInfo in methods)
|
||||||
{
|
{
|
||||||
var attr = methodInfo.GetCustomAttribute<LuaFunctionAttribute>();
|
var attr = methodInfo.GetCustomAttribute<LuaFunctionAttribute>();
|
||||||
if (attr != null)
|
if (attr != null)
|
||||||
{
|
{
|
||||||
dictionary.Add(attr.Name, new LuaMethodInfoFunction(new UserDataMethod(methodInfo), this));
|
dictionary.Add(attr.Name, new ScriptMethodInfoFunction(new UserDataMethod(methodInfo), this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace Upsilon.StandardLibraries
|
||||||
public static (EvaluationScope, BoundScope) CreateStandardLibrary()
|
public static (EvaluationScope, BoundScope) CreateStandardLibrary()
|
||||||
{
|
{
|
||||||
var basicFunctions = new BasicFunctions().LoadMethods();
|
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 =
|
var boundScope =
|
||||||
new BoundScope(
|
new BoundScope(
|
||||||
scope.Variables.ToDictionary(x => x.Key
|
scope.Variables.ToDictionary(x => x.Key
|
||||||
|
@ -56,7 +56,7 @@ namespace Upsilon.StandardLibraries
|
||||||
var luaVariable = value.ToLuaType();
|
var luaVariable = value.ToLuaType();
|
||||||
var varSymbol = new VariableSymbol(name, luaVariable.Type, false);
|
var varSymbol = new VariableSymbol(name, luaVariable.Type, false);
|
||||||
BoundScope.SetVariable(varSymbol);
|
BoundScope.SetVariable(varSymbol);
|
||||||
Scope.Set(varSymbol, luaVariable);
|
Scope.Set(varSymbol, luaVariable, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -79,5 +79,42 @@ return a
|
||||||
Assert.Equal(15, result);
|
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<long>();
|
||||||
|
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<long>();
|
||||||
|
Assert.Empty(script.Diagnostics.Messages);
|
||||||
|
Assert.Equal(6, result);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue