Implements remainder and exponent operators

This commit is contained in:
Deukhoofd 2018-12-07 15:29:46 +01:00
parent f504a8706e
commit 9bd82174f2
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
6 changed files with 71 additions and 13 deletions

View File

@ -1,3 +1,5 @@
using System;
namespace Upsilon.BaseTypes.Number
{
internal abstract class ScriptNumber : ScriptType
@ -41,6 +43,17 @@ namespace Upsilon.BaseTypes.Number
return new ScriptNumberDouble(((ScriptNumberLong) a).Value * ((ScriptNumberDouble) b).Value);
}
public static ScriptNumber operator % (ScriptNumber a, ScriptNumber b)
{
if (!a.IsFloat && !b.IsFloat)
return new ScriptNumberLong(((ScriptNumberLong) a).Value % ((ScriptNumberLong) b).Value);
if (a.IsFloat && b.IsFloat)
return new ScriptNumberDouble(((ScriptNumberDouble) a).Value % ((ScriptNumberDouble) b).Value);
if (a.IsFloat)
return new ScriptNumberDouble(((ScriptNumberDouble) a).Value % ((ScriptNumberLong) b).Value);
return new ScriptNumberDouble(((ScriptNumberLong) a).Value % ((ScriptNumberDouble) b).Value);
}
public static ScriptNumber operator / (ScriptNumber a, ScriptNumber b)
{
if (!a.IsFloat && !b.IsFloat)
@ -60,6 +73,18 @@ namespace Upsilon.BaseTypes.Number
return new ScriptNumberLong(-((ScriptNumberLong)n).Value);
}
public static ScriptNumber Exponent(ScriptNumber a, ScriptNumber b)
{
if (!a.IsFloat && !b.IsFloat)
return new ScriptNumberLong((long) Math.Pow(((ScriptNumberLong) a).Value, ((ScriptNumberLong) b).Value));
if (a.IsFloat && b.IsFloat)
return new ScriptNumberDouble(Math.Pow(((ScriptNumberDouble) a).Value, ((ScriptNumberDouble) b).Value));
if (a.IsFloat)
return new ScriptNumberDouble(Math.Pow(((ScriptNumberDouble) a).Value, ((ScriptNumberLong) b).Value));
return new ScriptNumberDouble(Math.Pow(((ScriptNumberLong) a).Value, ((ScriptNumberDouble) b).Value));
}
#region Equality
private bool Equals(ScriptNumber other)
@ -117,6 +142,7 @@ namespace Upsilon.BaseTypes.Number
public static explicit operator double(ScriptNumber n)
{
if (n.IsFloat)

View File

@ -15,7 +15,9 @@ namespace Upsilon.Binder
LessEquals,
Less,
And,
Or
Or,
Exponent,
Remainder
}
private Type LeftType { get; }
@ -46,6 +48,8 @@ namespace Upsilon.Binder
new BoundBinaryOperator(OperatorKind.Subtraction, Type.Number),
new BoundBinaryOperator(OperatorKind.Multiplication, Type.Number),
new BoundBinaryOperator(OperatorKind.Division, Type.Number),
new BoundBinaryOperator(OperatorKind.Exponent, Type.Number),
new BoundBinaryOperator(OperatorKind.Remainder, Type.Number),
// Number equality
new BoundBinaryOperator(OperatorKind.Equality, Type.Number, Type.Number, Type.Boolean),
@ -102,6 +106,12 @@ namespace Upsilon.Binder
case SyntaxKind.Slash:
kind = OperatorKind.Division;
break;
case SyntaxKind.PercentSign:
kind = OperatorKind.Remainder;
break;
case SyntaxKind.RoofSign:
kind = OperatorKind.Exponent;
break;
case SyntaxKind.EqualsEquals:
kind = OperatorKind.Equality;
break;

View File

@ -288,7 +288,7 @@ namespace Upsilon.Evaluator
}
goto default;
case BoundBinaryOperator.OperatorKind.Subtraction:
if (left.Type == Type.Number)
if (left.Type == Type.Number && right.Type == Type.Number)
{
return ((ScriptNumber)left) - ((ScriptNumber)right);
}
@ -301,7 +301,7 @@ namespace Upsilon.Evaluator
}
goto default;
case BoundBinaryOperator.OperatorKind.Multiplication:
if (left.Type == Type.Number)
if (left.Type == Type.Number && right.Type == Type.Number)
{
return ((ScriptNumber)left) * ((ScriptNumber)right);
}
@ -314,7 +314,7 @@ namespace Upsilon.Evaluator
}
goto default;
case BoundBinaryOperator.OperatorKind.Division:
if (left.Type == Type.Number)
if (left.Type == Type.Number && right.Type == Type.Number)
{
return ((ScriptNumber)left) / ((ScriptNumber)right);
}
@ -326,6 +326,18 @@ namespace Upsilon.Evaluator
return type;
}
goto default;
case BoundBinaryOperator.OperatorKind.Exponent:
if (left.Type == Type.Number && right.Type == Type.Number)
{
return ScriptNumber.Exponent((ScriptNumber) left, (ScriptNumber) right);
}
goto default;
case BoundBinaryOperator.OperatorKind.Remainder:
if (left.Type == Type.Number && right.Type == Type.Number)
{
return ((ScriptNumber)left) % ((ScriptNumber)right);
}
goto default;
case BoundBinaryOperator.OperatorKind.Equality:
return new ScriptBoolean(Equals(left, right));
case BoundBinaryOperator.OperatorKind.Inequality:

View File

@ -102,6 +102,10 @@ namespace Upsilon.Parser
return new SyntaxToken(SyntaxKind.Comma, _position, ",", null);
case '#':
return new SyntaxToken(SyntaxKind.PoundSign, _position, "#", null);
case '%':
return new SyntaxToken(SyntaxKind.PercentSign, _position, "%", null);
case '^':
return new SyntaxToken(SyntaxKind.RoofSign, _position, "^", null);
case '"':
return LexString();
case '=':

View File

@ -87,5 +87,7 @@ namespace Upsilon.Parser
NumericForStatement,
BreakStatement,
GenericForStatement,
PercentSign,
RoofSign
}
}

View File

@ -5,13 +5,12 @@ namespace Upsilon.Parser
public enum Precedence
{
None = 0,
Or,
And,
LogicalOr,
LogicalAnd,
Equality,
PlusMinus,
StarSlash,
Additive,
Multiplicative,
Unary,
Exponentiation
}
public static Precedence UnaryOperatorPrecedence(this SyntaxKind kind)
@ -44,18 +43,23 @@ namespace Upsilon.Parser
// logical operators
case SyntaxKind.AndKeyword:
return Precedence.And;
return Precedence.LogicalAnd;
case SyntaxKind.OrKeyword:
return Precedence.Or;
return Precedence.LogicalOr;
// math operators
case SyntaxKind.Plus:
case SyntaxKind.Minus:
return Precedence.PlusMinus;
return Precedence.Additive;
case SyntaxKind.Star:
case SyntaxKind.Slash:
return Precedence.StarSlash;
case SyntaxKind.PercentSign:
case SyntaxKind.RoofSign:
return Precedence.Multiplicative;
default:
return Precedence.None;
}