C# 准备语法树(ast)以轻松执行短路操作

C# 准备语法树(ast)以轻松执行短路操作,c#,syntax,compiler-construction,abstract-syntax-tree,short-circuiting,C#,Syntax,Compiler Construction,Abstract Syntax Tree,Short Circuiting,准备包含条件的语法树的最佳方法是什么,以方便快捷地使用short curcuit 一般来说,短路的规则非常简单: 如果和块中的一个组件返回false,则整个块将返回false,可以退出执行 如果或块中的一个组件返回true,则整个块将返回true,并且可以退出执行 因此,例如,这个简单语句将按照以下语法树计算1=0和1=1: and / \ = = / \ / \ 1 0 1 1 在这种情况下很容易。执行树(

准备包含条件的语法树的最佳方法是什么,以方便快捷地使用
short curcuit

一般来说,
短路
的规则非常简单:

  • 如果
    块中的一个组件返回false,则整个块将返回false,可以退出执行
  • 如果
    块中的一个组件返回true,则整个块将返回true,并且可以退出执行
  • 因此,例如,这个简单语句将按照以下语法树计算
    1=0和1=1

           and
        /      \
       =        =
     /  \      /  \
    1    0    1    1
    
    在这种情况下很容易。执行树(分支)的第一部分后, 执行将退出,它只能返回false。但是如果树长得更多 复杂的是,必须有一种更有效的方法。还是这已经是最重要的 有效的方法

    例如,在这种情况下,
    c#
    编译器如何评估语法树

    编辑

    如果
    true
    false
    不可能,我是否应该将所有条件写在一个简单的列表中,并分支到末尾?这样我就没有了
    部分了


    非常感谢大家

    您对短路的定义与C#和其他语言的定义不太匹配。在大多数(可能是所有)具有短路的语言中,行为仅取决于左操作数的值,即:

    • left&&right
      始终计算
      left
      ,并且仅在
      left
      为真时计算
      right

    • left | | right
      始终计算
      left
      并且仅在
      left
      为false时计算
      right

    因此,语言规则保证永远不会首先尝试正确的操作数,即使编译器可能认为首先尝试正确的操作数会更有效。这样您就知道
    list==null | | list.IsEmpty()
    永远不会抛出null指针异常

    因此,为了回答您的问题,编译器不会生成比“计算左操作数,然后仅在必要时计算右操作数”更高效的代码,因为任何其他代码都会破坏语言规则

    PS:理论上,如果编译器能够证明操作数没有任何副作用,那么它就有可能对操作数进行重新排序,但据我所知,这是不可能的。无论哪种方式,这都不会在AST级别发生


    PPS:C#编译器不计算AST,而是从中生成代码。这是一个编译器,而不是解释器。

    你对短路的定义与C#和其他语言的定义不太相符。在大多数(可能是所有)具有短路的语言中,行为仅取决于左操作数的值,即:

    • left&&right
      始终计算
      left
      ,并且仅在
      left
      为真时计算
      right

    • left | | right
      始终计算
      left
      并且仅在
      left
      为false时计算
      right

    因此,语言规则保证永远不会首先尝试正确的操作数,即使编译器可能认为首先尝试正确的操作数会更有效。这样您就知道
    list==null | | list.IsEmpty()
    永远不会抛出null指针异常

    因此,为了回答您的问题,编译器不会生成比“计算左操作数,然后仅在必要时计算右操作数”更高效的代码,因为任何其他代码都会破坏语言规则

    PS:理论上,如果编译器能够证明操作数没有任何副作用,那么它就有可能对操作数进行重新排序,但据我所知,这是不可能的。无论哪种方式,这都不会在AST级别发生


    PPS:C#编译器不计算AST,而是从中生成代码。这是一个编译器,不是解释器。

    如果我没弄错的话,编译器会尝试从左到右读取您的语句。对于每个组件,它将计算为
    True
    False
    。然后将检查下一步应该执行的操作(和/或)。根据上一个值的结果,它将选择是否评估条件的正确部分。这两部分的结果和逻辑运算符将用作下一部分的左侧部分。(我就是这样学的,所以这是最简单的方法)。C#编译器的工作原理可能会有所不同,请您回答。但是,如果“删除”树,并用一些标签、分支或某种goto将其列成一个简单的列表,这样它就只需要执行一些条件序列——跳过不需要的条件,不是更好吗?因此,执行部分不需要任何短路逻辑。例如:(分支命令)如果我没有弄错,编译器将尝试从左到右读取您的语句。对于每个组件,它将计算为
    True
    False
    。然后将检查下一步应该执行的操作(和/或)。根据上一个值的结果,它将选择是否评估条件的正确部分。这两部分的结果和逻辑运算符将用作下一部分的左侧部分。(我就是这样学的,所以这是最简单的方法)。C#编译器的工作原理可能会有所不同,请您回答。但是,如果“删除”树,并用一些标签、分支或某种goto将其列成一个简单的列表,这样它就只需要执行一些条件序列——跳过不需要的条件,不是更好吗?因此,执行部分不需要任何短路逻辑。例如:(分支命令)谢谢你的回答。你觉得这个计划怎么样