Skylark: SlicingExpression: do not create new nodes for optional expressions

RELNOTES: None.
PiperOrigin-RevId: 185353994
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SliceExpression.java b/src/main/java/com/google/devtools/build/lib/syntax/SliceExpression.java
index a2b6036..54c194a 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/SliceExpression.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/SliceExpression.java
@@ -16,14 +16,15 @@
 import com.google.devtools.build.lib.events.Location;
 import java.io.IOException;
 import java.util.List;
+import javax.annotation.Nullable;
 
 /** Syntax node for a slice expression, e.g. obj[:len(obj):2]. */
 public final class SliceExpression extends Expression {
 
   private final Expression object;
-  private final Expression start;
-  private final Expression end;
-  private final Expression step;
+  @Nullable private final Expression start;
+  @Nullable private final Expression end;
+  @Nullable private final Expression step;
 
   public SliceExpression(Expression object, Expression start, Expression end, Expression step) {
     this.object = object;
@@ -36,43 +37,32 @@
     return object;
   }
 
-  public Expression getStart() {
+  public @Nullable Expression getStart() {
     return start;
   }
 
-  public Expression getEnd() {
+  public @Nullable Expression getEnd() {
     return end;
   }
 
-  public Expression getStep() {
+  public @Nullable Expression getStep() {
     return step;
   }
 
   @Override
   public void prettyPrint(Appendable buffer) throws IOException {
-    boolean startIsDefault =
-        (start instanceof Identifier) && ((Identifier) start).getName().equals("None");
-    boolean endIsDefault =
-        (end instanceof Identifier) && ((Identifier) end).getName().equals("None");
-    boolean stepIsDefault =
-        (step instanceof IntegerLiteral) && ((IntegerLiteral) step).getValue() == 1;
-
     object.prettyPrint(buffer);
     buffer.append('[');
-    // Start and end are omitted if they are the literal identifier None, which is the default value
-    // inserted by the parser if no bound is given. Likewise, step is omitted if it is the literal
-    // integer 1.
-    //
     // The first separator colon is unconditional. The second separator appears only if step is
     // printed.
-    if (!startIsDefault) {
+    if (start != null) {
       start.prettyPrint(buffer);
     }
     buffer.append(':');
-    if (!endIsDefault) {
+    if (end != null) {
       end.prettyPrint(buffer);
     }
-    if (!stepIsDefault) {
+    if (step != null) {
       buffer.append(':');
       step.prettyPrint(buffer);
     }
@@ -82,9 +72,9 @@
   @Override
   Object doEval(Environment env) throws EvalException, InterruptedException {
     Object objValue = object.eval(env);
-    Object startValue = start.eval(env);
-    Object endValue = end.eval(env);
-    Object stepValue = step.eval(env);
+    Object startValue = start == null ? Runtime.NONE : start.eval(env);
+    Object endValue = end == null ? Runtime.NONE : end.eval(env);
+    Object stepValue = step == null ? Runtime.NONE : step.eval(env);
     Location loc = getLocation();
 
     if (objValue instanceof SkylarkList) {