 
   defaultRules = [
 
-    [CS.Program, -> if @block? and mayHaveSideEffects @block, [] then this else new CS.Program null]
-
-    # Turn the block into an expression
+    # If a program has no side effects, then it is the empty program
+    [CS.Program, ->
+      if @block? and mayHaveSideEffects @block, [] then this
+      else new CS.Program null
+    ]
+
+    # Turn blocks into an expressions
     [CS.Block, (inScope, ancestors) ->
       switch @statements.length
         when 0 then (new CS.Undefined).g()

        else @right
    ]

    [CS.AssignOp, ->
      return this unless @expression.instanceof CS.SeqOp
      new CS.SeqOp @expression.left, new CS.AssignOp @assignee, @expression.right
    ]

    [CS.While, (inScope) ->
      if isFalsey @condition
        return if mayHaveSideEffects @condition, inScope
          # while (falsey with side effects) -> the condition
          @condition
        else
          # while (falsey without side effects) -> nothing
          if block?
            declarationsFor @block
          else
            (new CS.Undefined).g()
      if isTruthy @condition
        # while (truthy without side effects) -> loop
        unless mayHaveSideEffects @condition, inScope
          return (new CS.Undefined).g() unless @block?
          return this if this instanceof CS.Loop

    #  (new CS.FunctionApplication @expression, args).g().p @line, @column
    #]

    # Produce the right operand when the left operand is null or undefined
    [CS.ExistsOp, -> if @left.instanceof CS.Null, CS.Undefined then @right else this]

    # Produce false when the expression is null or undefined
    [CS.UnaryExistsOp, -> if @expression.instanceof CS.Null, CS.Undefined then (new CS.Bool false).g() else this]

    # LogicalNotOp applied to a literal or !!
