diff --git a/Interpreter.Lib/IR/Ast/Impl/Nodes/Expressions/BinaryExpression.cs b/Interpreter.Lib/IR/Ast/Impl/Nodes/Expressions/BinaryExpression.cs index e2f005f2..2129fd41 100644 --- a/Interpreter.Lib/IR/Ast/Impl/Nodes/Expressions/BinaryExpression.cs +++ b/Interpreter.Lib/IR/Ast/Impl/Nodes/Expressions/BinaryExpression.cs @@ -1,5 +1,6 @@ using Interpreter.Lib.BackEnd; using Interpreter.Lib.IR.Ast.Visitors; +using Interpreter.Lib.IR.CheckSemantics.Visitors.SemanticChecker; namespace Interpreter.Lib.IR.Ast.Impl.Nodes.Expressions; @@ -28,6 +29,9 @@ public override IEnumerator GetEnumerator() protected override string NodeRepresentation() => Operator; + public override Type Accept(SemanticChecker visitor) => + visitor.Visit(this); + public override AddressedInstructions Accept(ExpressionInstructionProvider visitor) => visitor.Visit(this); } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Impl/Nodes/Expressions/UnaryExpression.cs b/Interpreter.Lib/IR/Ast/Impl/Nodes/Expressions/UnaryExpression.cs index 218b8da6..146bafcc 100644 --- a/Interpreter.Lib/IR/Ast/Impl/Nodes/Expressions/UnaryExpression.cs +++ b/Interpreter.Lib/IR/Ast/Impl/Nodes/Expressions/UnaryExpression.cs @@ -1,5 +1,6 @@ using Interpreter.Lib.BackEnd; using Interpreter.Lib.IR.Ast.Visitors; +using Interpreter.Lib.IR.CheckSemantics.Visitors.SemanticChecker; namespace Interpreter.Lib.IR.Ast.Impl.Nodes.Expressions; @@ -23,6 +24,9 @@ public override IEnumerator GetEnumerator() protected override string NodeRepresentation() => Operator; + public override Type Accept(SemanticChecker visitor) => + visitor.Visit(this); + public override AddressedInstructions Accept(ExpressionInstructionProvider visitor) => visitor.Visit(this); } \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Visitors/SemanticChecker/SemanticChecker.cs b/Interpreter.Lib/IR/CheckSemantics/Visitors/SemanticChecker/SemanticChecker.cs index 77e161d4..c0a8cc64 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Visitors/SemanticChecker/SemanticChecker.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Visitors/SemanticChecker/SemanticChecker.cs @@ -22,7 +22,9 @@ public class SemanticChecker : IVisitor, IVisitor, IVisitor, - IVisitor + IVisitor, + IVisitor, + IVisitor { private readonly IDefaultValueForTypeCalculator _calculator; @@ -147,4 +149,60 @@ public Type Visit(ConditionalExpression visitable) aSegment: visitable.Alternate.Segment, aType); } + + public Type Visit(BinaryExpression visitable) + { + var lType = visitable.Left.Accept(this); + var rType = visitable.Right.Accept(this); + + if (visitable.Operator != "::" && !lType.Equals(rType)) + throw new IncompatibleTypesOfOperands( + visitable.Segment, + left: lType, + right: rType); + + Type number = "number"; + Type @string = "string"; + Type boolean = "boolean"; + + return visitable.Operator switch + { + "+" when lType.Equals(number) => number, + "+" when lType.Equals(@string) => @string, + "+" => throw new UnsupportedOperation(visitable.Segment, lType, visitable.Operator), + "-" or "*" or "/" or "%" => lType.Equals(number) + ? number + : throw new UnsupportedOperation(visitable.Segment, lType, visitable.Operator), + "||" or "&&" => lType.Equals(boolean) + ? boolean + : throw new UnsupportedOperation(visitable.Segment, lType, visitable.Operator), + "==" or "!=" => boolean, + ">" or ">=" or "<" or "<=" => lType.Equals(number) + ? boolean + : throw new UnsupportedOperation(visitable.Segment, lType, visitable.Operator), + "++" => lType is ArrayType && rType is ArrayType + ? lType + : throw new UnsupportedOperation(visitable.Segment, lType, visitable.Operator), + "::" when lType is not ArrayType => throw new UnsupportedOperation(visitable.Segment, lType, + visitable.Operator), + "::" => rType.Equals(number) ? "void" : throw new ArrayAccessException(visitable.Segment, rType), + _ => "undefined" + }; + } + + public Type Visit(UnaryExpression visitable) + { + var eType = visitable.Expression.Accept(this); + + Type number = "number"; + Type boolean = "boolean"; + + return visitable.Operator switch + { + "-" when eType.Equals(number) => number, + "!" when eType.Equals(boolean) => boolean, + "~" when eType is ArrayType => number, + _ => throw new UnsupportedOperation(visitable.Segment, eType, visitable.Operator) + }; + } } \ No newline at end of file