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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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