Generic For Loops

This commit is contained in:
Deukhoofd 2018-11-23 18:18:07 +01:00
parent 2db4d0607e
commit 638394d25b
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
38 changed files with 530 additions and 327 deletions

View File

@ -1,8 +0,0 @@
namespace Upsilon.BaseTypes.LuaTypeInterfaces
{
public interface IIterable
{
bool Next(out LuaType key, out LuaType next);
void Reset();
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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()

View File

@ -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<VariableSymbol> Parameters { get; }
public EvaluationScope EvaluationScope { get; }
public LuaInternalFunction(ImmutableArray<VariableSymbol> parameters, BoundBlockStatement block,
public ScriptInternalFunction(ImmutableArray<VariableSymbol> 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());

View File

@ -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()

View File

@ -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();
}

View File

@ -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<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();
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<KeyValuePair<string, LuaType>> _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;
}
}
}

View File

@ -1,6 +1,6 @@
namespace Upsilon.BaseTypes
{
public abstract class LuaType
public abstract class ScriptType
{
public abstract Type Type { get; }
public abstract object ToCSharpObject();

View File

@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace Upsilon.BaseTypes.ScriptTypeInterfaces
{
internal interface IIterable
{
IEnumerator<(string Key, ScriptType value)> GetEnumerator();
}
}

View File

@ -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);
}
}

View File

@ -1,6 +1,6 @@
using Upsilon.Evaluator;
namespace Upsilon.BaseTypes.LuaTypeInterfaces
namespace Upsilon.BaseTypes.ScriptTypeInterfaces
{
internal interface IScopeOwner
{

View File

@ -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<LuaType> _objects;
private readonly IList<ScriptType> _objects;
public SimpleLuaTable(IList<LuaType> objects)
public SimpleScriptTable(IList<ScriptType> 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();
}

View File

@ -10,6 +10,6 @@ namespace Upsilon.BaseTypes
Function,
UserData,
Thread,
Table
Table,
}
}

View File

@ -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)
{

View File

@ -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))

View File

@ -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);
}

View File

@ -1,3 +1,5 @@
using Upsilon.BaseTypes.ScriptTypeInterfaces;
namespace Upsilon.BaseTypes.UserData
{
internal interface IUserData : IIndexable

View File

@ -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();
}
}
}

View File

@ -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;

View File

@ -33,7 +33,7 @@ namespace Upsilon.BaseTypes.UserData
private Dictionary<string, UserDataMethod> 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);

View File

@ -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<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);
}
}
}

View File

@ -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; }
}
}

View File

@ -26,6 +26,7 @@ namespace Upsilon.Binder
BoundFullstopIndexExpression,
BoundMultiAssignmentStatement,
BoundNumericForStatement,
BoundBreakStatement
BoundGenericForStatement,
BoundBreakStatement,
}
}

View File

@ -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;
}
}

View File

@ -9,32 +9,32 @@ namespace Upsilon.Evaluator
private readonly EvaluationScope _parentScope;
private EvaluationScope _getOnlyParentScope;
public readonly Dictionary<string, LuaType> Variables;
private readonly Dictionary<string, LuaType> _localVariables;
public readonly Dictionary<string, ScriptType> Variables;
private readonly Dictionary<string, ScriptType> _localVariables;
internal EvaluationScope(EvaluationScope parentScope)
{
_parentScope = parentScope;
Variables = new Dictionary<string, LuaType>();
_localVariables = new Dictionary<string, LuaType>();
Variables = new Dictionary<string, ScriptType>();
_localVariables = new Dictionary<string, ScriptType>();
}
internal EvaluationScope(Dictionary<string, LuaType> vars)
internal EvaluationScope(Dictionary<string, ScriptType> vars)
{
Variables = vars;
_localVariables = new Dictionary<string, LuaType>();
_localVariables = new Dictionary<string, ScriptType>();
}
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;
}
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;

View File

@ -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<string, LuaType> variables)
internal Evaluator(Diagnostics diagnostics, Dictionary<string, ScriptType> variables)
{
_diagnostics = diagnostics;
Scope = new EvaluationScope(variables);
@ -38,7 +38,7 @@ namespace Upsilon.Evaluator
return