Adds Unary length operator
This commit is contained in:
parent
2dc59c5f8b
commit
cd04486d16
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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}
|
||||||
|
|
Loading…
Reference in New Issue