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 namespace Upsilon.BaseTypes.Number
{ {
internal abstract class ScriptNumber : ScriptType internal abstract class ScriptNumber : ScriptType
@ -41,6 +43,17 @@ namespace Upsilon.BaseTypes.Number
return new ScriptNumberDouble(((ScriptNumberLong) a).Value * ((ScriptNumberDouble) b).Value); 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) public static ScriptNumber operator / (ScriptNumber a, ScriptNumber b)
{ {
if (!a.IsFloat && !b.IsFloat) if (!a.IsFloat && !b.IsFloat)
@ -60,6 +73,18 @@ namespace Upsilon.BaseTypes.Number
return new ScriptNumberLong(-((ScriptNumberLong)n).Value); 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 #region Equality
private bool Equals(ScriptNumber other) private bool Equals(ScriptNumber other)
@ -117,6 +142,7 @@ namespace Upsilon.BaseTypes.Number
public static explicit operator double(ScriptNumber n) public static explicit operator double(ScriptNumber n)
{ {
if (n.IsFloat) if (n.IsFloat)

View File

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

View File

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

View File

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

View File

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

View File

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