Bind unary operators
This commit is contained in:
parent
4e331712a8
commit
82dff87d4d
|
@ -51,6 +51,12 @@ namespace Upsilon.BaseTypes.Number
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
public static Number operator - (Number n)
|
||||||
|
{
|
||||||
|
if (n.IsFloat)
|
||||||
|
return new NumberDouble(-((NumberDouble)n).Value);
|
||||||
|
return new NumberLong(-((NumberLong)n).Value);
|
||||||
|
}
|
||||||
|
|
||||||
#region Equality
|
#region Equality
|
||||||
private bool Equals(Number other)
|
private bool Equals(Number other)
|
||||||
|
|
|
@ -28,7 +28,7 @@ namespace Upsilon.Binder
|
||||||
switch (e.Kind)
|
switch (e.Kind)
|
||||||
{
|
{
|
||||||
case SyntaxKind.UnaryExpression:
|
case SyntaxKind.UnaryExpression:
|
||||||
break;
|
return BindUnaryExpression((UnaryExpressionSyntax) e);
|
||||||
case SyntaxKind.BinaryExpression:
|
case SyntaxKind.BinaryExpression:
|
||||||
return BindBinaryExpression((BinaryExpressionSyntax) e);
|
return BindBinaryExpression((BinaryExpressionSyntax) e);
|
||||||
case SyntaxKind.LiteralExpression:
|
case SyntaxKind.LiteralExpression:
|
||||||
|
@ -49,14 +49,27 @@ namespace Upsilon.Binder
|
||||||
throw new NotImplementedException(e.Kind.ToString());
|
throw new NotImplementedException(e.Kind.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BoundExpression BindUnaryExpression(UnaryExpressionSyntax e)
|
||||||
|
{
|
||||||
|
var inExp = BindExpression(e.Expression);
|
||||||
|
var op = BoundUnaryOperator.Bind(e.Operator.Kind, inExp.Type);
|
||||||
|
if (op == null)
|
||||||
|
{
|
||||||
|
_diagnostics.LogUnknownUnaryOperator(e.Span, e.Operator.Kind, inExp.Type);
|
||||||
|
return inExp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BoundUnaryExpression(op, inExp, op.OutType);
|
||||||
|
}
|
||||||
|
|
||||||
private BoundExpression BindBinaryExpression(BinaryExpressionSyntax e)
|
private BoundExpression BindBinaryExpression(BinaryExpressionSyntax e)
|
||||||
{
|
{
|
||||||
var left = BindExpression(e.Left);
|
var left = BindExpression(e.Left);
|
||||||
var right = BindExpression(e.Right);
|
var right = BindExpression(e.Right);
|
||||||
var op = BoundBinaryOperator.BindBinaryOperator(e.Operator.Kind, left.Type, right.Type);
|
var op = BoundBinaryOperator.Bind(e.Operator.Kind, left.Type, right.Type);
|
||||||
if (op == null)
|
if (op == null)
|
||||||
{
|
{
|
||||||
_diagnostics.LogUnknownOperator(e.Span, e.Operator.Kind, left.Type, right.Type);
|
_diagnostics.LogUnknownBinaryOperator(e.Span, e.Operator.Kind, left.Type, right.Type);
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
return new BoundBinaryExpression(op, left, right, op.OutType);
|
return new BoundBinaryExpression(op, left, right, op.OutType);
|
||||||
|
|
|
@ -50,7 +50,7 @@ namespace Upsilon.Binder
|
||||||
new BoundBinaryOperator(OperatorKind.Inequality, Type.Boolean),
|
new BoundBinaryOperator(OperatorKind.Inequality, Type.Boolean),
|
||||||
};
|
};
|
||||||
|
|
||||||
public static BoundBinaryOperator BindBinaryOperator(SyntaxKind operatorToken, Type left, Type right)
|
public static BoundBinaryOperator Bind(SyntaxKind operatorToken, Type left, Type right)
|
||||||
{
|
{
|
||||||
OperatorKind kind;
|
OperatorKind kind;
|
||||||
switch (operatorToken)
|
switch (operatorToken)
|
||||||
|
|
|
@ -6,5 +6,6 @@ namespace Upsilon.Binder
|
||||||
|
|
||||||
BoundLiteralExpression,
|
BoundLiteralExpression,
|
||||||
BoundBinaryExpression,
|
BoundBinaryExpression,
|
||||||
|
BoundUnaryExpression
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
using Upsilon.BaseTypes;
|
||||||
|
|
||||||
|
namespace Upsilon.Binder
|
||||||
|
{
|
||||||
|
public class BoundUnaryExpression : BoundExpression
|
||||||
|
{
|
||||||
|
public override BoundKind Kind => BoundKind.BoundUnaryExpression;
|
||||||
|
public override Type Type { get; }
|
||||||
|
|
||||||
|
public BoundUnaryExpression(BoundUnaryOperator op, BoundExpression inExpression, Type type)
|
||||||
|
{
|
||||||
|
Operator = op;
|
||||||
|
InExpression = inExpression;
|
||||||
|
Type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoundExpression InExpression { get; }
|
||||||
|
public BoundUnaryOperator Operator { get; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Upsilon.Parser;
|
||||||
|
using Type = Upsilon.BaseTypes.Type;
|
||||||
|
|
||||||
|
namespace Upsilon.Binder
|
||||||
|
{
|
||||||
|
public class BoundUnaryOperator
|
||||||
|
{
|
||||||
|
public enum OperatorKind
|
||||||
|
{
|
||||||
|
Identity,
|
||||||
|
Negation,
|
||||||
|
LogicalNegation
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type InType { get; }
|
||||||
|
public Type OutType { get; }
|
||||||
|
public OperatorKind Kind { get; }
|
||||||
|
|
||||||
|
private BoundUnaryOperator(OperatorKind kind, Type inType, Type outType)
|
||||||
|
{
|
||||||
|
Kind = kind;
|
||||||
|
InType = inType;
|
||||||
|
OutType = outType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundUnaryOperator[] _operators= new BoundUnaryOperator[]
|
||||||
|
{
|
||||||
|
new BoundUnaryOperator(OperatorKind.Identity, Type.Number, Type.Number),
|
||||||
|
new BoundUnaryOperator(OperatorKind.Negation, Type.Number, Type.Number),
|
||||||
|
new BoundUnaryOperator(OperatorKind.LogicalNegation, Type.Boolean, Type.Boolean),
|
||||||
|
};
|
||||||
|
|
||||||
|
public static BoundUnaryOperator Bind(SyntaxKind operatorToken, Type inType)
|
||||||
|
{
|
||||||
|
OperatorKind kind;
|
||||||
|
switch (operatorToken)
|
||||||
|
{
|
||||||
|
case SyntaxKind.Plus:
|
||||||
|
kind = OperatorKind.Identity;
|
||||||
|
break;
|
||||||
|
case SyntaxKind.Minus:
|
||||||
|
kind = OperatorKind.Negation;
|
||||||
|
break;
|
||||||
|
case SyntaxKind.NotKeyword:
|
||||||
|
kind = OperatorKind.LogicalNegation;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception("Unknown unary operator token: " + operatorToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _operators.FirstOrDefault(op => op.Kind == kind && op.InType == inType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -45,10 +45,16 @@ namespace Upsilon
|
||||||
LogError($"Unknown Type found", eSpan);
|
LogError($"Unknown Type found", eSpan);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LogUnknownOperator(TextSpan eSpan, SyntaxKind text, Type leftType, Type rightType)
|
public void LogUnknownBinaryOperator(TextSpan eSpan, SyntaxKind text, Type leftType, Type rightType)
|
||||||
{
|
{
|
||||||
LogError($"No binary operator {text} found for types '{leftType}' and '{rightType}'", eSpan);
|
LogError($"No binary operator {text} found for types '{leftType}' and '{rightType}'", eSpan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void LogUnknownUnaryOperator(TextSpan eSpan, SyntaxKind text, Type inType)
|
||||||
|
{
|
||||||
|
LogError($"No unary operator {text} found for type '{inType}'", eSpan);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DiagnosticsMessage
|
public class DiagnosticsMessage
|
||||||
|
|
|
@ -16,12 +16,6 @@ namespace Upsilon.Evaluator
|
||||||
Script = script;
|
Script = script;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
public object Evaluate(ScriptSyntax e)
|
|
||||||
{
|
|
||||||
return EvaluateExpression(e.Statement);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
public object Evaluate(BoundScript e)
|
public object Evaluate(BoundScript e)
|
||||||
{
|
{
|
||||||
return EvaluateExpression(e.Statement);
|
return EvaluateExpression(e.Statement);
|
||||||
|
@ -35,28 +29,28 @@ namespace Upsilon.Evaluator
|
||||||
return ((BoundLiteralExpression) e).Value;
|
return ((BoundLiteralExpression) e).Value;
|
||||||
case BoundKind.BoundBinaryExpression:
|
case BoundKind.BoundBinaryExpression:
|
||||||
return EvaluateBinaryExpression((BoundBinaryExpression) e);
|
return EvaluateBinaryExpression((BoundBinaryExpression) e);
|
||||||
|
case BoundKind.BoundUnaryExpression:
|
||||||
|
return EvaluateUnaryExpression((BoundUnaryExpression) e);
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
private object EvaluateUnaryExpression(BoundUnaryExpression e)
|
||||||
private object EvaluateUnaryExpression(UnaryExpressionSyntax e)
|
|
||||||
{
|
{
|
||||||
var operand = EvaluateExpression(e.Expression);
|
var operand = EvaluateExpression(e.InExpression);
|
||||||
switch (e.Operator.Kind)
|
switch (e.Operator.Kind)
|
||||||
{
|
{
|
||||||
case SyntaxKind.Plus:
|
case BoundUnaryOperator.OperatorKind.Identity:
|
||||||
return operand;
|
return operand;
|
||||||
case SyntaxKind.Minus:
|
case BoundUnaryOperator.OperatorKind.Negation:
|
||||||
return -(double) operand;
|
return -((Number)operand);
|
||||||
case SyntaxKind.NotKeyword:
|
case BoundUnaryOperator.OperatorKind.LogicalNegation:
|
||||||
return !(bool)operand;
|
return !(bool) operand;
|
||||||
default:
|
default:
|
||||||
throw new Exception("Invalid Unary Operator: " + e.Operator.Kind);
|
throw new Exception("Invalid Unary Operator: " + e.Operator.Kind);
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
|
|
||||||
private object EvaluateBinaryExpression(BoundBinaryExpression e)
|
private object EvaluateBinaryExpression(BoundBinaryExpression e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -44,7 +44,7 @@ namespace Upsilon.Parser
|
||||||
if (Current.Kind == kind)
|
if (Current.Kind == kind)
|
||||||
return NextToken();
|
return NextToken();
|
||||||
|
|
||||||
_diagnostics.LogBadCharacter(new TextSpan(_position, 1));
|
_diagnostics.LogBadCharacter(Current.Span);
|
||||||
return new SyntaxToken(kind, Current.Span.Start, "", null);
|
return new SyntaxToken(kind, Current.Span.Start, "", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue