Adds Unary length operator
This commit is contained in:
@@ -6,7 +6,7 @@ using Upsilon.Text;
|
|||||||
|
|
||||||
namespace Upsilon.BaseTypes
|
namespace Upsilon.BaseTypes
|
||||||
{
|
{
|
||||||
internal class ScriptString : ScriptType, IIndexable
|
internal class ScriptString : ScriptType, IIndexable, ILengthType
|
||||||
{
|
{
|
||||||
public ScriptString(string value)
|
public ScriptString(string value)
|
||||||
{
|
{
|
||||||
@@ -85,6 +85,11 @@ namespace Upsilon.BaseTypes
|
|||||||
return Value;
|
return Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ScriptNumberLong Length()
|
||||||
|
{
|
||||||
|
return new ScriptNumberLong(Value.Length);
|
||||||
|
}
|
||||||
|
|
||||||
public ScriptType Get(Diagnostics diagnostics, TextSpan span, ScriptType index, EvaluationScope scope)
|
public ScriptType Get(Diagnostics diagnostics, TextSpan span, ScriptType index, EvaluationScope scope)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Upsilon.BaseTypes.Number;
|
||||||
using Upsilon.BaseTypes.ScriptTypeInterfaces;
|
using Upsilon.BaseTypes.ScriptTypeInterfaces;
|
||||||
using Upsilon.Binder;
|
using Upsilon.Binder;
|
||||||
using Upsilon.Evaluator;
|
using Upsilon.Evaluator;
|
||||||
@@ -8,7 +9,7 @@ using Upsilon.Text;
|
|||||||
|
|
||||||
namespace Upsilon.BaseTypes
|
namespace Upsilon.BaseTypes
|
||||||
{
|
{
|
||||||
internal class ScriptTable : ScriptType, IIndexable, IScopeOwner, IIterable
|
internal class ScriptTable : ScriptType, IIndexable, IScopeOwner, IIterable, ILengthType
|
||||||
{
|
{
|
||||||
public EvaluationScope EvaluationScope { get; }
|
public EvaluationScope EvaluationScope { get; }
|
||||||
|
|
||||||
@@ -66,5 +67,10 @@ namespace Upsilon.BaseTypes
|
|||||||
yield return variable.Key.ToScriptType();
|
yield return variable.Key.ToScriptType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ScriptNumberLong Length()
|
||||||
|
{
|
||||||
|
return new ScriptNumberLong(EvaluationScope.Variables.Count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
9
Upsilon/BaseTypes/ScriptTypeInterfaces/ILengthType.cs
Normal file
9
Upsilon/BaseTypes/ScriptTypeInterfaces/ILengthType.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using Upsilon.BaseTypes.Number;
|
||||||
|
|
||||||
|
namespace Upsilon.BaseTypes.ScriptTypeInterfaces
|
||||||
|
{
|
||||||
|
internal interface ILengthType
|
||||||
|
{
|
||||||
|
ScriptNumberLong Length();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Upsilon.BaseTypes.Number;
|
||||||
|
using Upsilon.BaseTypes.ScriptTypeInterfaces;
|
||||||
using Upsilon.Evaluator;
|
using Upsilon.Evaluator;
|
||||||
using Upsilon.Text;
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.BaseTypes.UserData
|
namespace Upsilon.BaseTypes.UserData
|
||||||
{
|
{
|
||||||
internal class DictionaryUserData : ScriptType, IUserData
|
internal class DictionaryUserData : ScriptType, IUserData, ILengthType
|
||||||
{
|
{
|
||||||
public IDictionary Dictionary { get; }
|
public IDictionary Dictionary { get; }
|
||||||
|
|
||||||
@@ -47,5 +50,10 @@ namespace Upsilon.BaseTypes.UserData
|
|||||||
{
|
{
|
||||||
return Dictionary.GetType();
|
return Dictionary.GetType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ScriptNumberLong Length()
|
||||||
|
{
|
||||||
|
return new ScriptNumberLong(Dictionary.Count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,7 @@ using Upsilon.Text;
|
|||||||
|
|
||||||
namespace Upsilon.BaseTypes.UserData
|
namespace Upsilon.BaseTypes.UserData
|
||||||
{
|
{
|
||||||
internal class ListUserData : ScriptType, IUserData, IIterable
|
internal class ListUserData : ScriptType, IUserData, IIterable, ILengthType
|
||||||
{
|
{
|
||||||
private IList List { get; }
|
private IList List { get; }
|
||||||
|
|
||||||
@@ -66,5 +66,10 @@ namespace Upsilon.BaseTypes.UserData
|
|||||||
yield return new ScriptNumberLong(i);
|
yield return new ScriptNumberLong(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ScriptNumberLong Length()
|
||||||
|
{
|
||||||
|
return new ScriptNumberLong(List.Count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11,10 +11,11 @@ namespace Upsilon.Binder
|
|||||||
{
|
{
|
||||||
Identity,
|
Identity,
|
||||||
Negation,
|
Negation,
|
||||||
LogicalNegation
|
LogicalNegation,
|
||||||
|
Length
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type InType { get; }
|
private Type InType { get; }
|
||||||
public Type OutType { get; }
|
public Type OutType { get; }
|
||||||
public OperatorKind Kind { get; }
|
public OperatorKind Kind { get; }
|
||||||
|
|
||||||
@@ -25,11 +26,13 @@ namespace Upsilon.Binder
|
|||||||
OutType = outType;
|
OutType = outType;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BoundUnaryOperator[] _operators= new BoundUnaryOperator[]
|
private static readonly BoundUnaryOperator[] Operators= {
|
||||||
{
|
|
||||||
new BoundUnaryOperator(OperatorKind.Identity, Type.Number, Type.Number),
|
new BoundUnaryOperator(OperatorKind.Identity, Type.Number, Type.Number),
|
||||||
new BoundUnaryOperator(OperatorKind.Negation, Type.Number, Type.Number),
|
new BoundUnaryOperator(OperatorKind.Negation, Type.Number, Type.Number),
|
||||||
new BoundUnaryOperator(OperatorKind.LogicalNegation, Type.Boolean, Type.Boolean),
|
new BoundUnaryOperator(OperatorKind.LogicalNegation, Type.Boolean, Type.Boolean),
|
||||||
|
new BoundUnaryOperator(OperatorKind.Length, Type.String, Type.Number),
|
||||||
|
new BoundUnaryOperator(OperatorKind.Length, Type.Table, Type.Number),
|
||||||
|
new BoundUnaryOperator(OperatorKind.Length, Type.UserData, Type.Number),
|
||||||
};
|
};
|
||||||
|
|
||||||
public static BoundUnaryOperator Bind(SyntaxKind operatorToken, Type inType)
|
public static BoundUnaryOperator Bind(SyntaxKind operatorToken, Type inType)
|
||||||
@@ -46,13 +49,16 @@ namespace Upsilon.Binder
|
|||||||
case SyntaxKind.NotKeyword:
|
case SyntaxKind.NotKeyword:
|
||||||
kind = OperatorKind.LogicalNegation;
|
kind = OperatorKind.LogicalNegation;
|
||||||
break;
|
break;
|
||||||
|
case SyntaxKind.PoundSign:
|
||||||
|
kind = OperatorKind.Length;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Exception("Unknown unary operator token: " + operatorToken);
|
throw new Exception("Unknown unary operator token: " + operatorToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inType == Type.Unknown)
|
if (inType == Type.Unknown)
|
||||||
return _operators.FirstOrDefault(op => op.Kind == kind);
|
return Operators.FirstOrDefault(op => op.Kind == kind);
|
||||||
return _operators.FirstOrDefault(op => op.Kind == kind && op.InType == inType);
|
return Operators.FirstOrDefault(op => op.Kind == kind && op.InType == inType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -211,7 +211,12 @@ namespace Upsilon.Evaluator
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
goto default;
|
goto default;
|
||||||
|
case BoundUnaryOperator.OperatorKind.Length:
|
||||||
|
if (operand is ILengthType length)
|
||||||
|
{
|
||||||
|
return length.Length();
|
||||||
|
}
|
||||||
|
goto default;
|
||||||
default:
|
default:
|
||||||
throw new Exception("Invalid Unary Operator: " + e.Operator.Kind);
|
throw new Exception("Invalid Unary Operator: " + e.Operator.Kind);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,6 +78,8 @@ namespace Upsilon.Parser
|
|||||||
return new SyntaxToken(SyntaxKind.FullStop, _position, ".", null);
|
return new SyntaxToken(SyntaxKind.FullStop, _position, ".", null);
|
||||||
case ',':
|
case ',':
|
||||||
return new SyntaxToken(SyntaxKind.Comma, _position, ",", null);
|
return new SyntaxToken(SyntaxKind.Comma, _position, ",", null);
|
||||||
|
case '#':
|
||||||
|
return new SyntaxToken(SyntaxKind.PoundSign, _position, "#", null);
|
||||||
case '"':
|
case '"':
|
||||||
return LexString();
|
return LexString();
|
||||||
case '=':
|
case '=':
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ namespace Upsilon.Parser
|
|||||||
CloseBrace,
|
CloseBrace,
|
||||||
OpenBracket,
|
OpenBracket,
|
||||||
CloseBracket,
|
CloseBracket,
|
||||||
|
PoundSign,
|
||||||
|
|
||||||
// key words
|
// key words
|
||||||
TrueKeyword,
|
TrueKeyword,
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ namespace Upsilon.Parser
|
|||||||
PlusMinus,
|
PlusMinus,
|
||||||
StarSlash,
|
StarSlash,
|
||||||
Unary,
|
Unary,
|
||||||
|
Exponentiation
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Precedence UnaryOperatorPrecedence(this SyntaxKind kind)
|
public static Precedence UnaryOperatorPrecedence(this SyntaxKind kind)
|
||||||
@@ -20,6 +21,7 @@ namespace Upsilon.Parser
|
|||||||
case SyntaxKind.Plus:
|
case SyntaxKind.Plus:
|
||||||
case SyntaxKind.Minus:
|
case SyntaxKind.Minus:
|
||||||
case SyntaxKind.NotKeyword:
|
case SyntaxKind.NotKeyword:
|
||||||
|
case SyntaxKind.PoundSign:
|
||||||
return Precedence.Unary;
|
return Precedence.Unary;
|
||||||
default:
|
default:
|
||||||
return Precedence.None;
|
return Precedence.None;
|
||||||
|
|||||||
27
UpsilonTests/GeneralTests/LengthOperatorTests.cs
Normal file
27
UpsilonTests/GeneralTests/LengthOperatorTests.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
using Upsilon.Binder;
|
||||||
|
using Upsilon.Evaluator;
|
||||||
|
using Upsilon.StandardLibraries;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace UpsilonTests.GeneralTests
|
||||||
|
{
|
||||||
|
public class LengthOperatorTests : TestClass
|
||||||
|
{
|
||||||
|
public LengthOperatorTests(StaticScriptFixture fix) : base(fix)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(@"#""test""", 4)]
|
||||||
|
[InlineData(@"#{100,50,60,7863,1564,12354,10354}", 7)]
|
||||||
|
public void Test(string input, long expectedOutput)
|
||||||
|
{
|
||||||
|
var script = new Script(input, BoundScope, StaticScope);
|
||||||
|
Assert.Empty(script.Diagnostics.Messages);
|
||||||
|
var actual = script.Evaluate<long>();
|
||||||
|
Assert.Empty(script.Diagnostics.Messages);
|
||||||
|
Assert.Equal(expectedOutput, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,7 +26,7 @@ namespace UpsilonTests.StandardLibraryTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void IPairsTest()
|
public void UpTillNilPairsTest()
|
||||||
{
|
{
|
||||||
const string input = @"
|
const string input = @"
|
||||||
arr = {100, 56, 28, nil, 100}
|
arr = {100, 56, 28, nil, 100}
|
||||||
|
|||||||
Reference in New Issue
Block a user