Rework for loops to use iterators, requiring pairs or ipairs function to handle multi-assignment
This commit is contained in:
parent
c63df3c941
commit
13ac6f2754
|
@ -0,0 +1,80 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Upsilon.BaseTypes.ScriptTypeInterfaces;
|
||||
|
||||
namespace Upsilon.BaseTypes
|
||||
{
|
||||
internal abstract class ScriptIterator : ScriptType, IIterable
|
||||
{
|
||||
public IIterable BaseIterator { get; }
|
||||
public override Type Type => Type.Table;
|
||||
|
||||
public ScriptIterator(IIterable baseIterator)
|
||||
{
|
||||
BaseIterator = baseIterator;
|
||||
}
|
||||
|
||||
public override object ToCSharpObject()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public override System.Type GetCSharpType()
|
||||
{
|
||||
return typeof(IEnumerator<ScriptType>);
|
||||
}
|
||||
|
||||
public ScriptType GetValueFromIndex(ScriptType index)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
public abstract IEnumerator<ScriptType> GetEnumerator();
|
||||
|
||||
}
|
||||
|
||||
internal class UpTillNullPairsScriptIterator : ScriptIterator
|
||||
{
|
||||
public UpTillNullPairsScriptIterator(IIterable baseIterator) : base(baseIterator)
|
||||
{
|
||||
}
|
||||
|
||||
public override IEnumerator<ScriptType> GetEnumerator()
|
||||
{
|
||||
using(var baseEnumerator = BaseIterator.GetEnumerator())
|
||||
{
|
||||
while (baseEnumerator.MoveNext())
|
||||
{
|
||||
var key = baseEnumerator.Current;
|
||||
if (key == null)
|
||||
break;
|
||||
var value = BaseIterator.GetValueFromIndex(key);
|
||||
if (value == null)
|
||||
break;
|
||||
yield return new SimpleScriptTable(new List<ScriptType>(){key, value});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class PairsScriptIterator : ScriptIterator
|
||||
{
|
||||
public PairsScriptIterator(IIterable baseIterator) : base(baseIterator)
|
||||
{
|
||||
}
|
||||
|
||||
public override IEnumerator<ScriptType> GetEnumerator()
|
||||
{
|
||||
using(var baseEnumerator = BaseIterator.GetEnumerator())
|
||||
{
|
||||
while (baseEnumerator.MoveNext())
|
||||
{
|
||||
var key = baseEnumerator.Current;
|
||||
var value = BaseIterator.GetValueFromIndex(key);
|
||||
yield return new SimpleScriptTable(new List<ScriptType>(){key, value});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Upsilon.BaseTypes.ScriptTypeInterfaces;
|
||||
|
@ -44,16 +45,25 @@ namespace Upsilon.BaseTypes
|
|||
EvaluationScope.CreateLocal(new VariableSymbol(s, value.Type, false), value);
|
||||
}
|
||||
|
||||
public IEnumerator<(string Key, ScriptType value)> GetEnumerator()
|
||||
public ScriptType GetValueFromIndex(ScriptType index)
|
||||
{
|
||||
if (EvaluationScope.TryGet(index.ToString(), out var result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
throw new Exception($"Can't find key '{index}' in table.");
|
||||
}
|
||||
|
||||
public IEnumerator<ScriptType> GetEnumerator()
|
||||
{
|
||||
return Enumerator();
|
||||
}
|
||||
|
||||
private IEnumerator<(string Key, ScriptType value)> Enumerator()
|
||||
private IEnumerator<ScriptType> Enumerator()
|
||||
{
|
||||
foreach (var variable in EvaluationScope.Variables)
|
||||
{
|
||||
yield return (variable.Key, variable.Value);
|
||||
yield return variable.Key.ToScriptType();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
using System.Collections.Generic;
|
||||
using Upsilon.Evaluator;
|
||||
|
||||
namespace Upsilon.BaseTypes.ScriptTypeInterfaces
|
||||
{
|
||||
internal interface IIterable
|
||||
{
|
||||
IEnumerator<(string Key, ScriptType value)> GetEnumerator();
|
||||
ScriptType GetValueFromIndex(ScriptType index);
|
||||
IEnumerator<ScriptType> GetEnumerator();
|
||||
}
|
||||
}
|
|
@ -38,6 +38,8 @@ namespace Upsilon.BaseTypes
|
|||
return _objects[i];
|
||||
}
|
||||
|
||||
public ScriptType this[int index] => _objects[index];
|
||||
|
||||
public void Set(Diagnostics diagnostics, TextSpan span, ScriptType index, ScriptType value)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Upsilon.BaseTypes.Number;
|
||||
using Upsilon.BaseTypes.ScriptTypeInterfaces;
|
||||
using Upsilon.Evaluator;
|
||||
using Upsilon.Text;
|
||||
|
@ -51,9 +53,18 @@ namespace Upsilon.BaseTypes.UserData
|
|||
return List.GetType();
|
||||
}
|
||||
|
||||
public IEnumerator<(string Key, ScriptType value)> GetEnumerator()
|
||||
public ScriptType GetValueFromIndex(ScriptType index)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
var num = (ScriptNumberLong)index;
|
||||
return List[(int) num.Value].ToScriptType();
|
||||
}
|
||||
|
||||
public IEnumerator<ScriptType> GetEnumerator()
|
||||
{
|
||||
for (int i = 0; i < List.Count; i++)
|
||||
{
|
||||
yield return new ScriptNumberLong(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -548,11 +548,17 @@ namespace Upsilon.Evaluator
|
|||
{
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
var (key, value) = enumerator.Current;
|
||||
var current = enumerator.Current;
|
||||
if (current == null || current.Type != Type.Table)
|
||||
{
|
||||
throw new Exception($"Can't assign result value with type '{current.Type}' to multiple values");
|
||||
}
|
||||
|
||||
var table = (SimpleScriptTable)current;
|
||||
if (e.Variables[0].Name != "_")
|
||||
innerEvaluator.Scope.CreateLocal(e.Variables[0], key.ToScriptType());
|
||||
innerEvaluator.Scope.CreateLocal(e.Variables[0], table[0].ToScriptType());
|
||||
if (e.Variables[1].Name != "_")
|
||||
innerEvaluator.Scope.CreateLocal(e.Variables[1], value);
|
||||
innerEvaluator.Scope.CreateLocal(e.Variables[1], table[1]);
|
||||
innerEvaluator.EvaluateBoundBlockStatement((BoundBlockStatement) e.Block);
|
||||
if (innerEvaluator.HasBroken)
|
||||
break;
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Upsilon.BaseTypes;
|
||||
using Upsilon.BaseTypes.Number;
|
||||
using Upsilon.BaseTypes.ScriptTypeInterfaces;
|
||||
using Type = Upsilon.BaseTypes.Type;
|
||||
|
||||
// ReSharper disable UnusedMember.Global
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
|
@ -28,11 +26,18 @@ namespace Upsilon.StandardLibraries
|
|||
}
|
||||
|
||||
[StandardLibraryScriptFunction("ipairs")]
|
||||
public IIterable UpTillNullPairs(IIterable table)
|
||||
{
|
||||
return new UpTillNullPairsScriptIterator(table);
|
||||
}
|
||||
|
||||
[StandardLibraryScriptFunction("pairs")]
|
||||
public IIterable Pairs(IIterable table)
|
||||
{
|
||||
return table;
|
||||
return new PairsScriptIterator(table);
|
||||
}
|
||||
|
||||
|
||||
[StandardLibraryScriptFunction("tonumber")]
|
||||
public ScriptNumber ToNumber(ScriptString obj)
|
||||
{
|
||||
|
|
|
@ -85,7 +85,7 @@ return a
|
|||
const string input = @"
|
||||
arr = {100, 56, 28}
|
||||
value = 0
|
||||
for key, val in arr do
|
||||
for key, val in ipairs(arr) do
|
||||
value = value + val
|
||||
end
|
||||
return value
|
||||
|
@ -103,7 +103,7 @@ return value
|
|||
const string input = @"
|
||||
arr = {100, 56, 28}
|
||||
value = 0
|
||||
for key, val in arr do
|
||||
for key, val in ipairs(arr) do
|
||||
local keyInt = tonumber(key)
|
||||
value = value + keyInt
|
||||
end
|
||||
|
|
|
@ -206,7 +206,7 @@ end
|
|||
const string input = @"
|
||||
arr = {100, 56, 28}
|
||||
value = 0
|
||||
for key, val in arr do
|
||||
for key, val in ipairs(arr) do
|
||||
value = value + tonumber(key)
|
||||
end
|
||||
return value
|
||||
|
|
|
@ -51,7 +51,7 @@ b = a
|
|||
const string input = @"
|
||||
arr = {100, 56, 28}
|
||||
local value = 0
|
||||
for key, val in arr do
|
||||
for key, val in ipairs(arr) do
|
||||
value = value + val
|
||||
end
|
||||
return value
|
||||
|
|
Loading…
Reference in New Issue