aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Florian Weikert <fwe@google.com>2015-11-09 16:06:49 +0000
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2015-11-10 10:23:05 +0000
commit1bf1c970cad8bd2f1b7b42b1038b87e10d6a5428 (patch)
treeaf321600847460c068ec315938d41e0c7a110017 /src
parent3ef1eea7b84841bb696ad6341b2503804fa6562c (diff)
Compile conditional statement and expressions.
-- MOS_MIGRATED_REVID=107385205
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/ConditionalExpression.java40
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/IfStatement.java54
2 files changed, 93 insertions, 1 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/ConditionalExpression.java b/src/main/java/com/google/devtools/build/lib/syntax/ConditionalExpression.java
index 652baa6555..be83c3144c 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/ConditionalExpression.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/ConditionalExpression.java
@@ -11,9 +11,22 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-
package com.google.devtools.build.lib.syntax;
+import static com.google.devtools.build.lib.syntax.compiler.ByteCodeUtils.append;
+
+import com.google.devtools.build.lib.syntax.compiler.ByteCodeUtils;
+import com.google.devtools.build.lib.syntax.compiler.DebugInfo;
+import com.google.devtools.build.lib.syntax.compiler.Jump;
+import com.google.devtools.build.lib.syntax.compiler.Jump.PrimitiveComparison;
+import com.google.devtools.build.lib.syntax.compiler.LabelAdder;
+import com.google.devtools.build.lib.syntax.compiler.VariableScope;
+
+import net.bytebuddy.implementation.bytecode.ByteCodeAppender;
+
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Syntax node for an if/else expression.
*/
@@ -67,4 +80,29 @@ public final class ConditionalExpression extends Expression {
thenCase.validate(env);
elseCase.validate(env);
}
+
+ @Override
+ ByteCodeAppender compile(VariableScope scope, DebugInfo debugInfo) throws EvalException {
+ List<ByteCodeAppender> code = new ArrayList<>();
+ LabelAdder afterLabel = new LabelAdder();
+ LabelAdder elseLabel = new LabelAdder();
+ // compile condition and convert to boolean
+ code.add(condition.compile(scope, debugInfo));
+ append(
+ code,
+ EvalUtils.toBoolean,
+ // jump to else block if false
+ Jump.ifIntOperandToZero(PrimitiveComparison.EQUAL).to(elseLabel));
+ // otherwise evaluate the expression for "then" and jump to end
+ code.add(thenCase.compile(scope, debugInfo));
+ append(
+ code,
+ Jump.to(afterLabel),
+ // add label for "else" and evaluate the expression
+ elseLabel);
+ code.add(elseCase.compile(scope, debugInfo));
+ append(code, afterLabel);
+
+ return ByteCodeUtils.compoundAppender(code);
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/IfStatement.java b/src/main/java/com/google/devtools/build/lib/syntax/IfStatement.java
index ffe29479bd..a40a4daf37 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/IfStatement.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/IfStatement.java
@@ -13,9 +13,22 @@
// limitations under the License.
package com.google.devtools.build.lib.syntax;
+import static com.google.devtools.build.lib.syntax.compiler.ByteCodeUtils.append;
+
+import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.syntax.compiler.ByteCodeUtils;
+import com.google.devtools.build.lib.syntax.compiler.DebugInfo;
+import com.google.devtools.build.lib.syntax.compiler.Jump;
+import com.google.devtools.build.lib.syntax.compiler.Jump.PrimitiveComparison;
+import com.google.devtools.build.lib.syntax.compiler.LabelAdder;
+import com.google.devtools.build.lib.syntax.compiler.LoopLabels;
+import com.google.devtools.build.lib.syntax.compiler.VariableScope;
+
+import net.bytebuddy.implementation.bytecode.ByteCodeAppender;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -66,6 +79,17 @@ public final class IfStatement extends Statement {
condition.validate(env);
validateStmts(env, stmts);
}
+
+ @Override
+ ByteCodeAppender compile(
+ VariableScope scope, Optional<LoopLabels> loopLabels, DebugInfo debugInfo)
+ throws EvalException {
+ List<ByteCodeAppender> code = new ArrayList<>();
+ for (Statement statement : stmts) {
+ code.add(statement.compile(scope, loopLabels, debugInfo));
+ }
+ return ByteCodeUtils.compoundAppender(code);
+ }
}
private final ImmutableList<ConditionalStatements> thenBlocks;
@@ -132,4 +156,34 @@ public final class IfStatement extends Statement {
}
env.finishTemporarilyDisableReadonlyCheckBranch();
}
+
+ @Override
+ ByteCodeAppender compile(
+ VariableScope scope, Optional<LoopLabels> loopLabels, DebugInfo debugInfo)
+ throws EvalException {
+ List<ByteCodeAppender> code = new ArrayList<>();
+ LabelAdder after = new LabelAdder();
+ LabelAdder nextConditionalOrElse;
+ for (ConditionalStatements statement : thenBlocks) {
+ nextConditionalOrElse = new LabelAdder();
+ // compile condition and convert to boolean
+ code.add(statement.getCondition().compile(scope, debugInfo));
+ append(
+ code,
+ EvalUtils.toBoolean,
+ // jump to next conditional/else block if false
+ Jump.ifIntOperandToZero(PrimitiveComparison.EQUAL).to(nextConditionalOrElse));
+ // otherwise execute the body and jump to end
+ code.add(statement.compile(scope, loopLabels, debugInfo));
+ append(code, Jump.to(after));
+ // add label for next conditional or the else block (which may be empty, but no matter)
+ append(code, nextConditionalOrElse);
+ }
+ for (Statement statement : elseBlock) {
+ code.add(statement.compile(scope, loopLabels, debugInfo));
+ }
+ append(code, after);
+
+ return ByteCodeUtils.compoundAppender(code);
+ }
}