public override object VisitAndExpression([NotNull] DoshikParser.AndExpressionContext context) { SetWholeExpression(context); VisitChildren(context); _compilationContext.SetParsingAntlrContext(context); var node = new AndExpressionNode(context); node.Left = Sequence.FindExpressionByAntlrContext(context.left); node.Right = Sequence.FindExpressionByAntlrContext(context.right); Sequence.Sequence.Add(node); return(null); }
// ToDo: Про перегрузку операторов op_ConditionalAnd (&&) и op_ConditionalOr (||) // Эти операторы перегружены только у bool. И зачем это сделано непонятно - это не обычный вызов функции. Эта булева // логика должна выполняться непосредственно компилятором, а не внешним вызовом. Видимо это было сделано просто для удобства работы в графах. // смысл в том что в случае выражения к примеру if (a != null && a.DoThings() == 5) внутри стоит оператор && - он должен сначала // посчитать истинность левого операнда и ТОЛЬКО ЕСЛИ он истинен - оператор может выполнить правый операнд. А при обычном вызове // метода сначала просчитываются все операнды (левый, правый) а потом только вызывается метод с этими операндами. Тут же действие должно // быть между просчетом левого и правого операнда, то есть его нельзя посчитать внешним вызовом, это должен делать компилятор - посмотреть // истинное ли выражение слева и сгенерировать по нему JUMP_IF_FALSE. То есть операнд справа НЕ ДОЛЖЕН ВЫПОЛНИТЬСЯ если операнд слева == false // Аналогичная ситуация с оператором || - но там я уже не помню как логика идет. // То есть надо вместо метода тут возвращать отдельный вид expression-а (можно сделать его общим для and/or) // // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/expressions#user-defined-conditional-logical-operators // x && y превращается в T.false(x) ? x : T.&(x, y) // x || y превращается в T.true(x) ? x : T.|(x, y) // можно попробовать возвращать в этих слуаях искусственно сгенерированый IfExpression // // Похожая ситуация идет при обработке оператора ifexpression - там тоже просчет операндов зависит от результата условия и там также идут JUMP_IF_FALSE private IExpression HandleAndExpressionNode(AndExpressionNode node) { // ToDo: читать выше - тут не должно быть вызова метода return(CreateStaticMethodCallExpressionForBinaryOperator("op_ConditionalAnd", node.Left, node.Right)); }