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.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Upsilon.BaseTypes.ScriptTypeInterfaces;
|
using Upsilon.BaseTypes.ScriptTypeInterfaces;
|
||||||
|
@ -44,16 +45,25 @@ namespace Upsilon.BaseTypes
|
||||||
EvaluationScope.CreateLocal(new VariableSymbol(s, value.Type, false), value);
|
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();
|
return Enumerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerator<(string Key, ScriptType value)> Enumerator()
|
private IEnumerator<ScriptType> Enumerator()
|
||||||
{
|
{
|
||||||
foreach (var variable in EvaluationScope.Variables)
|
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 System.Collections.Generic;
|
||||||
|
using Upsilon.Evaluator;
|
||||||
|
|
||||||
namespace Upsilon.BaseTypes.ScriptTypeInterfaces
|
namespace Upsilon.BaseTypes.ScriptTypeInterfaces
|
||||||
{
|
{
|
||||||
internal interface IIterable
|
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];
|
return _objects[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ScriptType this[int index] => _objects[index];
|
||||||
|
|
||||||
public void Set(Diagnostics diagnostics, TextSpan span, ScriptType index, ScriptType value)
|
public void Set(Diagnostics diagnostics, TextSpan span, ScriptType index, ScriptType value)
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
throw new System.NotImplementedException();
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Upsilon.BaseTypes.Number;
|
||||||
using Upsilon.BaseTypes.ScriptTypeInterfaces;
|
using Upsilon.BaseTypes.ScriptTypeInterfaces;
|
||||||
using Upsilon.Evaluator;
|
using Upsilon.Evaluator;
|
||||||
using Upsilon.Text;
|
using Upsilon.Text;
|
||||||
|
@ -51,9 +53,18 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
return List.GetType();
|
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())
|
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 != "_")
|
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 != "_")
|
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);
|
innerEvaluator.EvaluateBoundBlockStatement((BoundBlockStatement) e.Block);
|
||||||
if (innerEvaluator.HasBroken)
|
if (innerEvaluator.HasBroken)
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using Upsilon.BaseTypes;
|
using Upsilon.BaseTypes;
|
||||||
using Upsilon.BaseTypes.Number;
|
using Upsilon.BaseTypes.Number;
|
||||||
using Upsilon.BaseTypes.ScriptTypeInterfaces;
|
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
|
||||||
|
@ -28,11 +26,18 @@ namespace Upsilon.StandardLibraries
|
||||||
}
|
}
|
||||||
|
|
||||||
[StandardLibraryScriptFunction("ipairs")]
|
[StandardLibraryScriptFunction("ipairs")]
|
||||||
|
public IIterable UpTillNullPairs(IIterable table)
|
||||||
|
{
|
||||||
|
return new UpTillNullPairsScriptIterator(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
[StandardLibraryScriptFunction("pairs")]
|
||||||
public IIterable Pairs(IIterable table)
|
public IIterable Pairs(IIterable table)
|
||||||
{
|
{
|
||||||
return table;
|
return new PairsScriptIterator(table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[StandardLibraryScriptFunction("tonumber")]
|
[StandardLibraryScriptFunction("tonumber")]
|
||||||
public ScriptNumber ToNumber(ScriptString obj)
|
public ScriptNumber ToNumber(ScriptString obj)
|
||||||
{
|
{
|
||||||
|
|
|
@ -85,7 +85,7 @@ return a
|
||||||
const string input = @"
|
const string input = @"
|
||||||
arr = {100, 56, 28}
|
arr = {100, 56, 28}
|
||||||
value = 0
|
value = 0
|
||||||
for key, val in arr do
|
for key, val in ipairs(arr) do
|
||||||
value = value + val
|
value = value + val
|
||||||
end
|
end
|
||||||
return value
|
return value
|
||||||
|
@ -103,7 +103,7 @@ return value
|
||||||
const string input = @"
|
const string input = @"
|
||||||
arr = {100, 56, 28}
|
arr = {100, 56, 28}
|
||||||
value = 0
|
value = 0
|
||||||
for key, val in arr do
|
for key, val in ipairs(arr) do
|
||||||
local keyInt = tonumber(key)
|
local keyInt = tonumber(key)
|
||||||
value = value + keyInt
|
value = value + keyInt
|
||||||
end
|
end
|
||||||
|
|
|
@ -206,7 +206,7 @@ end
|
||||||
const string input = @"
|
const string input = @"
|
||||||
arr = {100, 56, 28}
|
arr = {100, 56, 28}
|
||||||
value = 0
|
value = 0
|
||||||
for key, val in arr do
|
for key, val in ipairs(arr) do
|
||||||
value = value + tonumber(key)
|
value = value + tonumber(key)
|
||||||
end
|
end
|
||||||
return value
|
return value
|
||||||
|
|
|
@ -51,7 +51,7 @@ b = a
|
||||||
const string input = @"
|
const string input = @"
|
||||||
arr = {100, 56, 28}
|
arr = {100, 56, 28}
|
||||||
local value = 0
|
local value = 0
|
||||||
for key, val in arr do
|
for key, val in ipairs(arr) do
|
||||||
value = value + val
|
value = value + val
|
||||||
end
|
end
|
||||||
return value
|
return value
|
||||||
|
|
Loading…
Reference in New Issue