Rework for loops to use iterators, requiring pairs or ipairs function to handle multi-assignment

This commit is contained in:
Deukhoofd 2018-11-24 14:35:23 +01:00
parent c63df3c941
commit 13ac6f2754
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
10 changed files with 132 additions and 16 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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